2016-02-25 3 views
0

Ниже приведен вопрос, но с разницей в разнице. Мне нужно получить строку, которая имеет «abc», когда есть соответствие «efg» в другой строке. И мне нужна только последняя искомая строка «ABC» до «EFG» сопоставляется ...Несколько строк, повторное совпадение

How to find patterns across multiple lines using grep?

blah blah.. 
blah blah.. 
blah abc blah1 
blah blah.. 
blah blah.. 
blah abc blah2 
blah blah.. 
blah efg1 blah blah 
blah efg2 blah blah 
blah blah.. 
blah blah.. 

blah abc blah3 
blah blah.. 
blah blah.. 
blah abc blah4 
blah blah.. 
blah blah blah 

blah abc blah5 
blah blah.. 
blah blah.. 
blah abc blah6 
blah blah.. 
blah efg3 blah blah 

blah efg4 blah blah 
blah abc blah7 
blah blah.. 
blah blah.. 
blah abc blah8 
blah blah.. 

Ожидаемый результат

blah abc blah2 
blah abc blah6 

ответ

0

Это может работать для вас (GNU СЭД):

sed -n '/abc/h;/efg/!b;x;/abc/p;z;x' file 

магазин последняя abc линия в трюма (ГС). Когда встречается строка, содержащая efg, переключитесь на HS, и если эта строка содержит abc, распечатайте ее.

+0

пытается понять синтаксис, https://www.gnu.org/software/sed/manual/sed.html, но не смог понять «/! B», не могли бы вы немного объяснить? – user3663854

+0

@ user3663854 адрес можно отрицать добавлением '!' И объясняется команда 'b' [здесь] (https://www.gnu.org/software/sed/manual/sed.html#Programming-Commands). – potong

0

Я могу видеть, как сделать это в двух шаги, один для идентификации блоков abc ... efg кластеров, но с несколькими из первых. Второй шаг - разделить на две линии, которые имеют значение.

Важно: убедитесь, что на входеотсутствуют пары пустых строк, так как это приведет к поломке шага perl.

grep -Pzo '(.*abc.*)\n(.*\n)*?(.*efg.*\n)' text | perl -0777 -pe 's/(.+\n)*(.*abc.*\n)(.+\n)*?(.*efg.*\n)\n/$2$4/g' 

Например:

grep -Pzo '(.*abc.*)\n(.*\n)*?(.*efg.*\n)' text 
blah abc blah1 
blah blah.. 
blah blah.. 
blah abc blah2 
blah blah.. 
blah efg1 blah blah 

blah abc blah3 
blah blah.. 
blah blah.. 
blah abc blah4 
blah blah.. 
blah blah blah 
blah abc blah5 
blah blah.. 
blah blah.. 
blah abc blah6 
blah blah.. 
blah efg3 blah blah 

Посмотрите, как efg ломти разделены двумя строками? Затем удалить хлама, который не имеет значения с PERL поиска и замены регулярных выражений:

$ grep -Pzo '(.*abc.*)\n(.*\n)*?(.*efg.*\n)' text | perl -0777 -pe 's/(.+\n)*(.*abc.*\n)(.+\n)*?(.*efg.*\n)\n/$2$4/g' 
blah abc blah2 
blah efg1 blah blah 
blah abc blah6 
blah efg3 blah blah 

Если вы просто хотите abc линию, просто включите $2 в замене блока (удалить $4).

$ grep -Pzo '(.*abc.*)\n(.*\n)*?(.*efg.*\n)' text | perl -0777 -pe 's/(.+\n)*(.*abc.*\n)(.+\n)*?(.*efg.*\n)\n/$2/g' 
blah abc blah2 
blah abc blah6 
Смежные вопросы