Использовать sed, как заменить шаблон, если он встречается в строке, следующей за другим шаблоном?

Скажем, следующее является содержимым файла

$ cat file Name=Tom Value=10 Name=Tom Name=Harry Value=20 

В некоторых случаях значение не возникает после имени. Поэтому мне нужно найти шаблон Name = Tom и заменить значение, но только если оно встречается в строке сразу после имени. Как это сделать?

  • как извлечь часть текста из файла между согласованными условиями
  • Найдите строку с двумя последними символами в виде числовых
  • подсчеты совпадений и несоответствий
  • Удалите первые n байтов файлов
  • Как добавить возврат каретки перед каждой новой линией?
  • замените с начала строки на 1 из нескольких шаблонов в конец другой строки со вторым шаблоном
  • Как добавить строку в первое поле вывода с помощью awk?
  • grep и найдите следующее значение:
  • 3 Solutions collect form web for “Использовать sed, как заменить шаблон, если он встречается в строке, следующей за другим шаблоном?”

    Более компактный и несколько более простой:

     sed 'G;/^Value=/s/=.*\nName=Tom/=42/;s/\n.*//;h' file 

    Это добавляет предыдущую строку из пространства удержания в каждую строку. Для строк Value= значение заменяется, если Name=Tom находился в удержании. В противном случае добавленная строка будет удалена, и строка будет сохранена в удержании для следующего цикла.

    с awk :

     awk 'prev ~ /^Name=(Tom|Anything)$/ && /^Value=/ {$0 = "Value=123"} {print; prev = $0}' 

    Или с именем и новым значением, хранящимся в переменной:

     export NAME=Tom VALUE=123 awk 'prev == "Name=" ENVIRON["NAME"] && /^Value=/ { $0 = "Value=" ENVIRON["VALUE"] } {print; prev = $0}' 

    С sed эквивалент будет примерно таким:

     sed -e 'x;/^Name=Tom$/{g;/^Value/s/=.*/=123/;h;b' -e '}' -eg 

    Хотя, как обычно, он короче, но значительно менее разборчив, чем с awk . Кроме того, для работы с произвольными значениями, хранящимися в переменных, sed не имеет эквивалента ENVIRON awk или возможности простого сравнения строк (в отличие от сопоставления регулярных выражений), поэтому вам нужно предварительно обработать значения переменных сначала, если вы не можете гарантировать, что переменные не содержат символов, специальных для sed .

     sed -e "x;/^Name=$NAME\$/{g;/^Value/s/=.*/=$VALUE/;h;b" -e '}' -eg 

    Было бы уязвимостью ввода команд (по крайней мере, с GNU sed ), если $NAME и $VALUE не будут жестко контролироваться.

     sed -e ' /^Name=Tom$/!b $!N /\(\nValue\)=.*/s//\1=NEW_VALUE/ P;D ' data.inp 

    объяснение

    • Он будет искать строки с именем Tom в них. Неправильное совпадение будет передано в стандартный вывод.
    • Затем он попытается добавить следующую строку в пространство шаблонов, если это не последняя строка.
    • Будем искать значение регулярного выражения = в только что добавленной строке, и если да, то значение изменяется на NEW_VALUE (вы должны изменить его на все, что вам нужно).
    • P; D => будет печатать часть пространства шаблонов слева от \ n, т. Е. Te prev line, которая имела Name = Tom, а затем удаляет эту часть. Теперь мы остаемся со значением = NEW_VALUE и с этим перескакиваем в начало строки сценария sed: / ^ Name = Tom $ /! B Очевидно, что это произойдет, и, следовательно, оно будет перенесено на стандартный вывод. Это делается для ухода за последовательными линиями Name = Tom.

    Результаты

     Name=Tom Value=NEW_VALUE Name=Tom Name=Harry Value=20 
    Interesting Posts

    Почему IP-адрес для Linux Bridge, который является виртуальным устройством уровня 2?

    Как выполнить зависимости модулей ядра?

    Что использовать, когда команда «ls» не работает?

    Как предотвратить закрытие терминала при запуске программы с завершением?

    GHOST: переполнение буфера glibc gethostbyname

    Совместное использование контента / приложений между консолью и консолью VNC

    Индивидуальный формат писем Bugzilla

    sudo script – лучшая практика?

    Медленное время отклика с помощью оболочки Gnome в полноэкранном режиме Virtualbox

    CasperJS и PHP In Cron Job не могут открывать файлы, отлично работают при запуске Manualy

    Ошибка: iptables: нет цепочки / цели / соответствия этим именем

    Где я могу найти схему ссылок для тематики GNOME 3 (например, Adwaita)?

    Что такое диалоговое окно пароля в Плимуте?

    Использование сжатых RAM-дисков для свопинга в FreeBSD на ранней доске Raspberry Pi

    Можем ли мы использовать два расширения фигурных скобок вместе?

    Linux и Unix - лучшая ОС в мире.