Bash: замена шаблона в определенном столбце, но только в строках между двумя шаблонами - PullRequest
0 голосов
/ 04 сентября 2018

У меня есть файлы с такой структурой:

abc
def
ghi
...
x x y x x
x x z x x
x x y x x
...
JKL
x x y x x
x x z x x
x x y x x
...
...
*empty line*
mno
pqr
...
...

Я хотел бы скопировать весь файл в новый файл, но с некоторыми изменениями. Во-первых, я хочу повлиять только на строки между шаблоном JKL и следующей пустой строкой. Кроме того, мне нужно заменить каждое вхождение шаблона y новым шаблоном NEW, но только если он появляется в третьем столбце.

Я пытался использовать sed, но я застрял в том, как выбрать столбцы:

sed -ne '/JKL/,/^$/s/y/NEW/'

это, конечно, заменило y на NEW во всех столбцах.

Я также попытался найти awk, но я смог найти только примеры двух отдельных потребностей, которые у меня были, и не смог соединить их. Как я мог это сделать?

Ответы [ 3 ]

0 голосов
/ 04 сентября 2018

awk также допускает синтаксис диапазона, аналогичный sed, см. Как выбрать линии между двумя шаблонами? для альтернативных и более гибких способов

awk '/JKL/,/^$/{if($3=="y") $3="NEW"} 1' ip.txt 
  • /JKL/,/^$/ интересные темы
    • if($3=="y") если значение 3-го поля в точности соответствует строке y
    • $3="NEW" изменить значение 3-го поля на нужный текст
    • если вам нужно использовать регулярные выражения, используйте sub(/y/, "NEW", $3) или gsub(/y/, "NEW", $3)
  • 1 идиоматический способ печати содержимого $0
0 голосов
/ 04 сентября 2018

Использование GNU awk и split(). Сначала еще несколько описательных тестовых данных:

...
JKL
 x x y x x
    x  y  z  x  x

...

Тогда скрипт:

$ awk '
/JKL/,/^ *$/ {                 # the desired block 
    n=split($0,a,FS,seps)      # split and store the separators
    b=seps[0]                  # seps[0] has the leading space, init buffer with it
    for(i=1;i<=n;i++) {        # iterate all fields
        if(i==3 && a[i]=="y")  # if 3rd field is y
            a[i]="NEW"         # replace it with with NEW
        b=b a[i] seps[i]       # build the buffer for output
    }
    print b
}' file

и вывод:

JKL
 x x NEW x x
    x  y  z  x  x
0 голосов
/ 04 сентября 2018

Третий столбец - это то, что следует за началом строки, последовательностью непробельных символов, пробелами, другой последовательностью непробельных символов и, наконец, пробелом:

sed '/^JKL$/,/^$/s/^\([^ ][^ ]* [^ ][^ ]*\) y /\1 NEW /'

или, если ваш sed поддерживает -r или -E:

sed -E '/^JKL$/,/^$/s/^([^ ]+ [^ ]+) y /\1 NEW /' 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...