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

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 

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

С sed :

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

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


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

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

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

  8AC3 remove 8AE4 8AE5 8AE6 remove 

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

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

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

  cmd output 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 \nl 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) 
 awk ' !/remove/ && NR > 1 && prev !~ /remove/ {print prev} {prev = $0} END {if (!/remove/) print} ' Input.txt 
 gawk 'BEGIN{ RS="remove\n"; ORS="" } RT{ print gensub("[^\n]*\n$","","") }; !RT{ print }' file 

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

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

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

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

Вывод:

 8B0F 8AC0 8AE4 8AE5