Вот еще один способ с sed:
sed '/foo/,$!d;H;/bar/!d;s/.*//;x;s/\n//' infile
Он добавляет каждую строку в /foo/,$диапазоне (строки, !не входящие в этот диапазон, dвыбираются) в Hстарое пространство. Линии, которые не совпадают bar, затем удаляются. На совпадающих строках пространство образца освобождается, e xизменяется с пространством удержания, а ведущая пустая строка в пространстве образца удаляется.
При огромных входных данных и небольшом числе случаев barэто должно быть (намного) быстрее, чем вытягивать каждую строку в пространство шаблона, а затем каждый раз проверять пространство шаблона bar.
Разъяснение:
sed '/foo/,$!d # delete line if not in this range
H # append to hold space
/bar/!d # if it doesn't match bar, delete
s/.*// # otherwise empty pattern space and
x # exchange hold buffer w. pattern space then
s/\n// # remove the leading newline
' infile
Конечно, если это файл (и помещается в памяти), вы можете просто запустить:
ed -s infile<<'IN'
.t.
/foo/,?bar?p
q
IN
потому что ed можно искать вперед и назад.
Вы даже можете прочитать вывод команды в текстовый буфер, если ваша оболочка поддерживает подстановку процесса:
printf '%s\n' .t. /foo/,?bar?p q | ed -s <(your command)
или, если это не так, с помощью gnu ed:
printf '%s\n' .t. /foo/,?bar?p q | ed -s '!your command'
fooи последнееbarи распечатаете все между ними, если что-нибудь. С потоком вам придется читать до первойfooи буферизовать все последующие строки в памяти до EOF, очищая буфер каждый раз, когдаbarпросматривается a . Это может означать буферизацию всего потока в памяти.