Замените строку, если предыдущие строки совпадают

#string #sed #replace

Вопрос:

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

Допустим, у меня есть следующий файл:

 targets {
        type = pppcfg_target_internet;
        name = "internet";
        only_crypt_auth = no;
        local {
                username = "";
                passwd = "";
 

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

Итак, что я хотел бы сделать:

Замените «имя пользователя» и «пароль«, если есть «тип = pppcfg_target_internet;» несколькими строками ранее.

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

Итак, «Если в 5-10 строках над строкой поиска есть «pppcfg_target_internet«, замените «пароль» и «имя пользователя«.

Я буду рад получить любую помощь. Также для рекомендации, следует ли использовать «ask» или «sed».

Ответ №1:

Вы можете использовать sed для выбора диапазона текста между определенными строками, которые вы хотите заменить, например, следующим образом

 sed '/pppcfg_target_internet/,/}/s/passwd.*/passwd = "newpass"/g'
 

Это означает, что между строками с «pppcfg_target_internet» и «}» найдите и замените строку, начинающуюся с passwd, следующей строкой: ‘passwd = «newpass»‘

Может быть, было бы неплохо создать какое-нибудь уникальное окончание блока

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

1. Большое спасибо! Надеюсь, вы не возражаете, если я немного расширю свой вопрос. Допустим, строка, которую я хочу заменить, находится в «FILE_A.txt» и я хочу заменить его строкой из «FILE_B.txt». Как бы мне пришлось корректировать ваше предложение, если бы я работал в двух разных файлах?

2. Если FILE_B.txt содержит одну строку, вы можете прочитать ее раньше. По умолчанию команда чтения будет считывать строку в переменную ОТВЕТА: read FILE_B.txt amp;amp; sed "/pppcfg_target_internet/,/}/s/passwd.*/passwd = "$REPLY"/g"

Ответ №2:

Это может сработать для вас (GNU sed):

 sed -E '/^[^n]*pppcfg_target_internet/{:a;N;/passwd/!ba
        s/^([^n]*n){5,10}[^n]*$/amp;/;Tb
        s/(username = ).*/1"new user";/m
        s/(passwd = ).*/1"new pass";/m};:b;P;D' file
 

Соберите строки между type = pppcfg_target_internet; и passwd , а затем замените новые значения пользователя и пароля.

N. B. Использование m флага в команде substitute для обеспечения подстановки происходит только для этой совпадающей строки. Также обратите внимание, что если количество собранных строк меньше 5 или больше 10, коллекция игнорируется.

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

1. Большое вам спасибо, к сожалению, это для меня не работает.