Как напечатать строку, если эта строка или следующая строка не содержат определенную строку

8

input.txt:

    8B0C
    remove
    8B0D
    remove
    8B0E
    remove
    8B0F
    8B10
    remove
    8B14
    remove
    8B15
    remove
    8B16
    remove
    8B17
    remove
    8AC0
    8AC1
    remove
    8AC2
    remove
    8AC3
    remove
    8AE4
    8AE5
    8AE6
    remove

Желаемый вывод:

    8B0F
    8AC0
    8AE4
    8AE5

Я хочу напечатать строку, если эта строка или следующая строка не содержат «удалить». Я использую солярис 5.10, KSH.

ayrton_senna
источник
@don_crissti Спасибо, я могу пометить этот вопрос как ответивший, если вы отправите свой ответ вместо комментариев.
ayrton_senna

Ответы:

14

С sed:

sed '$!N;/remove/!P;D' infile

Это вытягивает Nстроку ext в пространство образца (если не !в последней $строке) и проверяет, совпадает ли пространство образца remove. Если это не так (означает, что ни одна из двух строк в шаблонном пространстве не содержит строку remove), он Pпечатается до первого \nсимвола линии смещения (т.е. печатает первую строку). Затем он Dподнимается до первого \nсимвола Ewline и перезапускает цикл. Таким образом, в шаблонном пространстве не может быть более двух строк.


Это , вероятно , легче понять N, P, Dцикл , если добавить lдо и после того , как Nсмотреть на картины пространства:

sed 'l;$!N;l;/remove/!P;D' infile

Итак, используя только последние шесть строк из вашего примера:

    8AC3
    remove
    8AE4
    8AE5
    8AE6
    remove

последняя команда выводит:

    8AC3 $
    8AC3 \ n удалить $
    удалить $
    удалить \ n 8AE4 $
    8AE4 $
    8AE4 \ n 8AE5 $
    8AE4
    8AE5 $
    8AE5 \ n 8AE6 $
    8AE5
    8AE6 $
    8AE6 \ n удалить $
    удалить $
    удалить $

Вот краткое объяснение:

CMD выходной CMD
l     8AC3$                  N # read in the next line
l     8AC3\n    remove$      D # delete up to \n (pattern space matches so no P)
l     remove$                N # read in the next line
l     remove\n    8AE4$      D # delete up to \n (pattern space matches so no P)
l     8AE4$                  N # read in the next line
l     8AE4\n    8AE5$        # pattern space doesn't match so print up to \n
P     8AE4                   D # delete up to \n
l     8AE5$                  N # read in the next line
l     8AE5\n    8AE6$        # pattern space doesn't match so print up to \n
P     8AE5                   D # delete up to \n 
l     8AE6$                  N # read in the next line
l     8AE6\n    remove$      D # delete up to \n (pattern space matches so no P)
l     remove$                # last line so no N 
l     remove$                D # delete (pattern space matches so no P)
don_crissti
источник
5
awk '
    !/remove/ && NR > 1 && prev !~ /remove/ {print prev} 
    {prev = $0} 
    END {if (!/remove/) print}
' Input.txt 
Гленн Джекман
источник
2
gawk 'BEGIN{ RS="remove\n"; ORS="" }
      RT{ print gensub("[^\n]*\n$","","") }; !RT{ print }' file

Вышеупомянутый метод не читает записи построчно , скорее он читает многострочные записи от одного разделителя записей (RS) к следующему (или концу файла) - самой RSстроке «удалить» (включая ее завершающий `\ n).

!RTТест необходим для того, когда последняя строка не является RSстрока.
RT, Простак-изм , фактический текст текущей записи - х RS.
gensubэто также зеваки .

Если вам нужно проверить строку маркера, которая соответствует «удалить» в любом месте строки, вместо строки, которая равна «удалить», просто измените разделитель записей на:

`RS="[^\n]*remove[^\n]*\n"`  

Вывод:

8B0F
8AC0
8AE4
8AE5
Peter.O
источник