2016-02-25 115 views
0

我參考下面的問題,但有點不同。只有在「efg」匹配不同行時,才需要獲取具有「abc」的行。而我只需要安裝最新匹配的「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):

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

商店的最新abc線保持空間(HS)。當遇到包含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簇的塊,但具有多個前者。第二步是剝離重要的兩條線。

重要提示:確保在輸入\n\n中沒有空行對,因爲這將破壞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