Заменить конкретную строку с помощью sed

Заменить конкретную строку с помощью sed

06.02.2020 05:57:58 Просмотров 28 Источник

У меня есть код.текстовый файл, который содержит код Морзе например

.- ... - ...

У меня есть функция декодирования в Баш файл под названием морс , так как это:

decode (){ 
   sed -i 's/ \.-/A/g' $1
   sed -i 's/ \.-./R/g' $1
   cat $1
}

Когда я набираю в терминале $bash morse decode code.txt

Я получаю:

AA.

Выход, который я хочу, это :

АР

Как он может видеть отдельные строки .- есть и свои .- ... это Р ?

У вопроса есть решение - Посмотреть?

Ответы - Заменить конкретную строку с помощью sed / Replace specific string using sed

Является ответом!
Wiktor Stribiżew

06.02.2020 06:01:59

Вам нужно запустить s/ \.-\./R/gзамена первая. Обратите внимание на второе .должен быть экранирован, чтобы соответствовать только точке.

Следовательно, используйте

sed 's/ \.-\./R/g;s/ \.-/A/g' file

Смотрите онлайн-демонстрацию

Или по-другому:

sed -e 's/ \.-\./R/g' -e 's/ \.-/A/g' file

Замените fileв "$1".

ОБНОВЛЕНИЕ

Вот перевод функции кодирования / декодирования Python, опубликованный Матиасом ниже:

#!/bin/bash

### Encoding:

declare -A MORSE=( [A]='.-' [B]='-...' [C]='-.-.' [D]='-..' [E]='.' [F]='..-.' [G]='--.' [H]='....' [I]='..' [J]='.---' [K]='-.-' [L]='.-..' [M]='--' [N]='-.' [O]='---' [P]='.--.' [Q]='--.-' [R]='.-.' [S]='...' [T]='-' [U]='..-' [V]='...-' [W]='.--' [X]='-..-' [Y]='-.--' [Z]='--..' [1]='.----' [2]='..---' [3]='...--' [4]='....-' [5]='.....' [6]='-....' [7]='--...' [8]='---..' [9]='----.' [0]='-----' [',']='--..--' ['.']='.-.-.-' [';']='-.-.-.' [':']='---...' ['?']='..--..' ['!']='-.-.--' ['/']='-..-.' ['-']='-....-' ['+']='.-.-.' ['(']='-.--.' [')']='-.--.-' ['_']='..--.-' ['"']='.-..-.' ["'"]='.----.' ['$']='...-..-' ['@']='.--.-.' ['&']='.-...' ['  ']=' '  )

function encode {
  res=''
  s="$1"
  for (( i=0; i<${#s}; i++ )); do
    letter="${s:$i:1}"
    if [[ "$letter" == ' ' ]]; then
      res="${res}  "
    else
      res="${res}${MORSE[${letter^^}]} ";
    fi
  done
  printf "%s" "$res"
}

echo "$(encode "THIS IS FINE")"

### Now, decoding

declare -A MORSEDEC=( ['-.--.-']=')' ['..--..']='?' ['--..--']=', ' ['-....-']='-' ['.-.-.-']='.' ['...--']='3' ['-.--.']='(' ['---..']='8' ['-..-.']='/' ['....-']='4' ['-....']='6' ['----.']='9' ['.----']='1' ['..---']='2' ['.....']='5' ['--...']='7' ['-----']='0' ['-...']='B' ['-..-']='X' ['-.-.']='C' ['--..']='Z' ['--.-']='Q' ['.-..']='L' ['-.--']='Y' ['..-.']='F' ['.--.']='P' ['.---']='J' ['...-']='V' ['....']='H' ['-..']='D' ['---']='O' ['..-']='U' ['...']='S' ['.--']='W' ['-.-']='K' ['.-.']='R' ['--.']='G' ['-.']='N' ['..']='I' ['--']='M' ['.-']='A' ['  ']=' ' ['.']='E' ['-']='T' )

function decode {
  res=''
  tmp="$(sed 's/ \{2,\}/ | /g' <<< "$1")";
  for word in $tmp; do
    if [[ "$word" == '|' ]]; then
      res="${res}${MORSEDEC['  ']}";
    else
      res="${res}${MORSEDEC[$word]}";
    fi
  done
  printf "%s" "$res"
}
echo "$(decode "- .... .. ...   .. ...   ..-. .. -. .")"

Смотрите демо-версию Bash онлайн .

https://stackoverflow.com/questions/60097838/replace-specific-string-using-sed/60097908#comment106291108_60097908
Да, но это был пример..Что я могу сделать в случае наличия всех букв алфавита..Например И "Л" есть .- .. это означает, что я должен сделать то же самое для L
https://stackoverflow.com/questions/60097838/replace-specific-string-using-sed/60097908#comment106291147_60097908
@P. Bes это та же самая идея: более длинные паттерны должны обрабатываться перед более короткими.
Matias Barrios

06.02.2020 07:26:26

Если ваше намерение состоит в том, чтобы кодировать и декодировать сообщения Морзе с помощью любого инструмента, то что-то вроде этого будет сделано :

#!/usr/local/bin/python3
import re

alphabet = { 'A':'.-', 'B':'-...', 'C':'-.-.', 'D':'-..', 'E':'.', 'F':'..-.', 'G':'--.', 'H':'....', 'I':'..', 'J':'.---', 'K':'-.-', 'L':'.-..', 'M':'--', 'N':'-.', 'O':'---', 'P':'.--.', 'Q':'--.-', 'R':'.-.', 'S':'...', 'T':'-', 'U':'..-', 'V':'...-', 'W':'.--', 'X':'-..-', 'Y':'-.--', 'Z':'--..', '1':'.----', '2':'..---', '3':'...--', '4':'....-', '5':'.....', '6':'-....', '7':'--...', '8':'---..', '9':'----.', '0':'-----', ', ':'--..--', '.':'.-.-.-', '?':'..--..', '/':'-..-.', '-':'-....-', '(':'-.--.', ')':'-.--.-',' ':'  '} 

def encode(message): 
    return "".join([ ( alphabet[letter.upper()] + ' ' ) if letter != ' ' else '  ' for letter in message])

def decode(message):
    return "".join([ list(alphabet.keys())[list(alphabet.values()).index(item if item != '|' else '  ')] for item in re.sub(r' {2,}', ' | ',message).split(' ')])

print(encode('THIS IS FINE'))
print(decode('- .... .. ...   .. ...   ..-. .. -. .'))

Надеюсь, это тоже поможет.

https://stackoverflow.com/questions/60097838/replace-specific-string-using-sed/60099507#comment106294282_60099507
Это хорошая попытка. Я ищу что-то подобное, но в файле bash с unix, а не в python..Я был бы признателен, если бы вы помогли мне там.
https://stackoverflow.com/questions/60097838/replace-specific-string-using-sed/60099507#comment106295641_60099507
@P. Bes Ну вы на правильном пути, если это ваша цель. сед выглядит хорошим началом. Давайте посмотрим, сколько из этого скрипта Python я могу перевести на Bash. Вы можете использовать awk по крайней мере? или тебе нужен чистый Баш?
https://stackoverflow.com/questions/60097838/replace-specific-string-using-sed/60099507#comment106300260_60099507
чистый Баш я думаю
Gem Taylor

06.02.2020 08:29:36

Простой ответ в двигателях RE, которые поддерживают look-ahead и look-behind, состоял бы в том, чтобы рассматривать пространства как триггеры look-ahead и look-behind, но sed не поддерживает это.

Другой вариант, который позволяет избежать необходимости упорядочивать буквы, - это вводить дополнительные символы, чтобы помочь вам пометить каждую букву. Скажем, мы вводим = вокруг каждого пространства, затем мы можем заменить разделенные последовательности в любом порядке и, наконец, избавиться от разделителей:

echo  .- .-.|sed -e 's/^\(.*\)$/=\1=/;s/ /= =/g' -e 's/=\.-\.=/=R=/g;s/=\.-=/=A=/g' -e 's/= =//g;s/^=//;s/=$//'

Если у вас есть правила, которые должны сохранять несколько пространств, то это можно приспособить.

Ivan

06.02.2020 11:32:47

Ничего себе интересная идея! На основе алфавита @MatiasBarrios я сделал это.

#!/bin/bash

string=$1

declare -A morse=(
    [A]='.-'    [B]='-...'  [C]='-.-.'  [D]='-..'   [E]='.'
    [F]='..-.'  [G]='--.'   [H]='....'  [I]='..'    [J]='.---'
    [K]='-.-'   [L]='.-..'  [M]='--'    [N]='-.'    [O]='---'
    [P]='.--.'  [Q]='--.-'  [R]='.-.'   [S]='...'   [T]='-'
    [U]='..-'   [V]='...-'  [W]='.--'   [X]='-..-'  [Y]='-.--'
    [Z]='--..'

    [1]='.----'  [2]='..---'  [3]='...--'  [4]='....-'  [5]='.....'
    [6]='-....'  [7]='--...'  [8]='---..'  [9]='----.'  [0]='-----'
    [(]='-.--.'  [)]='-.--.-' [/]='-..-.'  [-]='-....-' [+]='.-.-.'
    [.]='.-.-.-' [,]='--..--' [?]='..--..' [!]='-.-.--' [ ]='  '
)

morse () {
    while [[ "$string" ]]; do
        symbol="${string::1}"
        printf -- "${morse["${symbol^}"]} "
        string="${string:1}"
    done
}

demorse () {
    declare -A demorse
    for item in "${!morse[@]}"; { demorse["${morse["$item"]}"]="$item"; }
    while [[ $@ ]]; do
        printf -- "${demorse["$1"],}"
        shift
    done
}

case $string in
    demorse) shift; demorse "$@";;
    *      )          morse     ;;
esac

Использование

$ ./morse 'hello world!'
.... . .-.. .-.. ---    .-- --- .-. .-.. -.. -.-.--

Demorse также worsk, но пробелы должны быть напечатаны вот так ' '

$ ./morse demorse .... . .-.. .-.. --- '  ' .-- --- .-. .-.. -.. -.-.--
hello world!
Закрыть X