Находите и заменяйте текст в файле только после совпадения двух разных шаблонов с помощью `sed` или `awk`.

Это расширение вопроса, заданного здесь: найти и заменить текст в файле после совпадения с шаблоном только для первого появления с помощью sed.

Проблема в том, что мне нужно выполнить поиск и замену, но только после первого появленияpattern1с последующимpattern2. Вот гдеpattern3поиск и замена должны произойти.

Использование варианта образца файла из связанного вопроса:

      Server 'Test AB'
    option type 'sa'
    option port '1234'
    option timeout '60'

Server 'Test AB'
    option type 'sb'
    option port '1234'
    option timeout '60'

Server 'Test EF'
    option type 'sa'
    option port '1234'
    option timeout '60'

Server 'Test GH'
    option type 'sa'
    option port '1234'
    option timeout '60'

Мне нужно это:

      Server 'Test AB'
    option type 'sa'
    option port '1234'
    option timeout '60'

Server 'Test AB'
    option type 'sb'
    option port '9876'
    option timeout '60'

Server 'Test EF'
    option type 'sa'
    option port '1234'
    option timeout '60'

Server 'Test GH'
    option type 'sa'
    option port '1234'
    option timeout '60'

Первые два имени совпадают. Для каждого сервера они разные. Мне нужно соответствовать определенномуServerимя (Test AB), а затемoption type(sb), а затем измените номер порта.

Я не знаю, как объединить несколько шаблонов в логическую цепочку.AND.

Какие-нибудь советы?sedилиawkрешения являются предпочтительными (но для хардкорных шейных бород, ищущих настоящую задачу, попробуйте сделать это с помощью чистой замены BASH. BASH 5 и более поздних версий подойдет). Спасибо.

1 ответ

позволяет указать диапазоны адресов в форме. В связанном ответе используется диапазон. Теперь вам нужно вложить диапазоны.

      sed "
/^Server 'Test AB'$/,/^$/ {
/option type 'sb'/,/option port '/ s/option port '.*'/option port '2222'/
}" file

Это означает: от (и включая) строки до (и включая) следующей пустой строки применить код внутри .

А код внутри означает: от (и включая) строки, содержащей, до (и включая) строки, содержащейoption port 'применить команду.

Иs/…/…/команда означает: в каждой строке заменить первое вхождениеoption port '.*'(где.*жадно соответствует нулю или более символам) сoption port '2222'.

Примечания:

  • К счастью, есть пустые строки, которые мы можем использовать для завершения диапазона. Без них у нас возникло бы искушение указать диапазоны от до . Проблема заключается в первом диапазоне от до следующего появленияServerбудет включать второе появление ; И вsedдиапазоны, обнаруженные одним и тем жеaddr1,addr2фрагмент кода не может перекрываться. Фактически второе появление не будет рассматриваться как начало нового диапазона, поэтому код внутри{}не будет выполняться для строк в этом разделе.

  • ^и являются якорями для начала и конца строки соответственно. Я использовал их сServer 'Test AB'но я сознательно не использовал их сoption type 'sb'. Настройте код под свои нужды.

  • Я использовал двойные кавычки, потому что данные содержат одинарные кавычки. Обычно вам нужно экранировать в двойных кавычках, но здесь мы имеем/сразу после каждого;$/не является допустимым именем для переменной оболочки и для чего-либо, что оболочка хотела бы расширить, поэтому нет необходимости экранировать$.

Другие вопросы по тегам