sed условно добавляется к строке после сопоставления шаблона

#bash #shell #unix #awk #sed

#bash #оболочка #unix #awk #sed

Вопрос:

У меня есть файл (тест) со следующим содержимым, которое необходимо отредактировать.

тест

 foo:
bar:hello
  

В настоящее время я использую sed для сопоставления с шаблоном и добавления строки в конец строки.

 sed -ie "/^bar/ s/$/,there" test
  

Что дает мне ожидаемый результат, т.е.

 foo:
bar:hello,there
  

Но проблема в том, что запятая (,) должна быть там, когда строка не заканчивается : . иначе это становится похоже:

 sed -ie "/^foo/ s/$/,there" test
  

Вывод:

 foo:,there
bar:hello
  

Требование:

 foo:there
bar:hello
  

Итак, возможно ли каким-либо образом проверить наличие шаблона, после проверки соответствия последнему символу строки, в зависимости от последнего символа, добавить строку в конец строки.

PS: я не могу установить отдельный пакет.

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

1. Если вы хотите добавить «there» к строке «foo:», то зачем вообще проверять наличие «bar»?

2. это «foo» или «bar» поступает в качестве входных данных. Итак, я получаю его в переменной и использую эту переменную внутри sed.

Ответ №1:

Сохраняйте простоту и просто используйте awk:

 $ awk '/^foo/{$0 = $0 (/:$/ ? "" : ",") "there"} 1' file
foo:there
bar:hello

$ awk '/^bar/{$0 = $0 (/:$/ ? "" : ",") "there"} 1' file
foo:
bar:hello,there
  

Обратите внимание, что все исходные строки ( foo or bar ), the : , the , , the $ и заменяющий текст ( there ) указаны только один раз? Это одна из вещей, которые вы хотите в программном обеспечении — минимальная избыточность.

Вышеуказанное будет работать с использованием любого awk в любой оболочке в любом UNIX-блоке.

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

1. хотя ответ проще, чем sed, awk выполняет дополнительную работу по записи изменений в тот же файл, в то время как с sed это проще.

2. @RatDon точно так же, как и в GNU sed -i , GNU awk должен -i inplace делать то же самое.

Ответ №2:

Вот один из способов использования t после успешной замены для перехода от второй s/// команды:

 $ cat test
foo:
bar:
bar:hello
bar:
bar:hello
bar:
bar:hello

$ sed '/^bar/ {s/:$/:there/;t;s/$/, there/}' test 
foo:
bar:there
bar:hello, there
bar:there
bar:hello, there
bar:there
bar:hello, there
  

Ответ №3:

Шаблоны перед вашими командами sed — это ваши условия. Вы должны знать, что вы можете указать несколько команд -e для sed.

Вот ваш код снова, но я игнорирую foo и bar . Я обращаю внимание только на последний символ:

 sed -i -e '/[^:]$/s/$/,there/' -e '/:$/s/$/there/' test
  

/[^:]$/ — это любой символ, который не является двоеточием в конце строки. /:$/ — это дополнение (любая строка, заканчивающаяся двоеточием).

Вот результаты:

 $ sed  -e '/[^:]$/s/$/,there/' -e '/:$/s/$/there/' test
foo:there
bar:hello,there
  

Ответ №4:

попробуйте gnu sed для обоих,

 sed -E '/^(foo|bar)/ s/:$/amp;there/;n; s/[^:]$/amp;,there/' test