Замените точное совпадающее слово, содержащее специальный символ

#bash #shell

Вопрос:

Я пытаюсь заменить слово в строке, содержащей то же слово, специальным символом в нем.

Пример:

string="this is a joke. this is a poor-joke. this is a joke-club"

Я просто хочу заменить слово «шутка» на «кока-кола», а не на специальный символ.

приведенная ниже команда заменяет все слово шутка.

 [chandu@mynode ~]$ echo $string | sed "s/joke/coke/g;"
this is a coke. this is a poor-coke. this is a coke-club

 

Я пробовал использовать sed "s/<joke>/coke/g;"
но даже это заменяет все слова

Ожидаемый результат: this is a coke. this is a poor-joke. this is a joke-club

Комментарии:

1. Зачем вы используете /g флаг, если это не то, чего вы хотите?

2. Я не совсем понимаю, что вы имеете в виду под особым характером. Не могли бы вы привести нам пример, который работает не так, как ожидалось?

3. разве точка . не является особым символом?

4. приведенная выше строка является примером. Мой фактический файл огромен и содержит слово «шутка» несколько раз. Это причина, по которой я пользуюсь /g .

Ответ №1:

Вы можете сами сопоставить начало и окончание слова, если хотите включить - его в качестве символа слова.

 $ sed 's/(^|[^a-zA-Z-])joke([^a-zA-Z-]|$)/1coke2/g' <<<"$string"
this is a coke. this is a poor-joke. this is a joke-club
 

Ответ №2:

Использование perl и look-around для определения благоприятных начальных (пробел) и конечных (пробел или точка) символов вокруг слова joke :

 $ echo $string | perl -p -e 's/(?<=[ ])joke(?=[. ])/coke/g'
 

Выход.

 this is a coke. this is a poor-joke. this is a joke-club
 

Комментарии:

1. Как насчет этой строки : this is a joke. this is a poor-joke. this is a joke ?

2. @Philippe Каковы ожидаемые результаты? Если вы ссылаетесь на слово joke в конце строки, измените группу символов для положительного прогноза на [. n] .

3. … или к (?=([. ]|$)) . Так, наверное, лучше.

4. Да, я имел в виду слово «шутка» в конце строки, Разумно, ОП ожидает, что его заменят.

Ответ №3:

К сожалению, в вашем случае дефис разделяет строку на разные слова.

т. е.: если я изменю вашу строку на:

 string='this is a joke. this is a poorjoke. this is a jokeclub'
 

и я выполняю команду:

 echo $string | sed 's/bjokeb/coke/g'
 

(где b означает: граница слова), я получаю следующий результат:

 this is a coke. this is a poorjoke. this is a jokeclub
 

Но когда я применяю ту же команду к вашей строке, я получаю (как и вы):

 this is a coke. this is a poor-coke. this is a coke-club
 

Итак, в вашем конкретном случае я бы попробовал что-то вроде:

 echo $string | sed 's/([^-])(joke)([^-])/1coke3/g'
 

Что приводит к следующему результату:

 this is a coke. this is a poor-joke. this is a joke-club