2016-08-12 48 views
0

說我有一些行的文件兩個模式之間的內容:awk中提取與至少匹配

a1 - first match /a/ 
b - other stuff 
a2 - last match /a/ 
b 
c - first match /c/ 
c - last match /c/ 

當我執行awk '/a/,/c/' file我會得到

a1 - first match /a/ 
b - other stuff 
a2 - last match /a/ 
b 
c - first match /c/ 

我想要做的是讓/ a /和/ c /之間的中間部分。但模式/ a /和/ c /匹配幾行,在這些行之間還有一些其他的東西。所以我想知道是否有一個簡單的方法來得到如下結果:

a2 - last match /a/ 
b 
c - first match /c/ 
+0

什麼是這裏的邏輯積累線?你還有其他的例子嗎? a和c總是出現兩次?它可以有多個塊? – fedorqui

+0

開始模式和停止模式匹配幾行,但我只想要中間部分。假設我們有'a \ na \ n \ nb \ nc \ nc \ nc \ n',我想要獲得'a \ nb \ nc \ n' – bitweaver

+0

將輸出管道到'uniq'以擺脫重複。 – Barmar

回答

1

你不能用範圍表達式來做到這一點。您需要匹配a並開始收集變量中的行。如果遇到另一個a,則必須清除該變量並重新開始。最後,當你看到c時,你打印這個變量。

awk '/^a/ { var = $0; flag = 1; next } 
    flag { var = var "\n" $0 } 
    /^c/ && flag { print var; flag = 0; var = "" }' file 
+0

我打算髮布這個回答'awk'/^a/{f = 1; buf =「」} f {buf = buf $ 0 RS}/^ c/{printf「%s」,buf; F = 0; buf =「」}'文件「,但它幾乎與你的一樣,所以加1給你,而我的輕微的替代語法在評論中! –

0

既然你沒有辦法知道這是最後一次的模式出現,直到你讀所有的文件,它可能是最好要經過兩次:第一次獲得行比賽,第二個數量來打印內的那些行:

awk 'FNR==NR && /^a/ {p1=FNR; next}   # last match of /a/ 
    FNR==NR && /^c/ && !p2 {p2=FNR; next} # first match of /c/ 
    (FNR >= p1) && (FNR <= p2)' file file 

使用特技FNR==NRIdiomatic awk描述來區分從第二個所述第一環路。

有了這個文件,這將返回:

$ awk 'FNR==NR && /^a/ {p1=FNR; next} FNR==NR && /^c/ && !p2 {p2=FNR; next} (FNR >= p1) && (FNR <= p2)' file file 
a2 - last match /a/ 
b 
c - first match /c/ 
+0

不應該是'> ='和'<=',因爲他想在輸出中包含'a'和'c'行嗎? – Barmar

+0

@Barmar你是對的。修正了,謝謝! – fedorqui

0

另一awk在一個陣列,而不是

$ awk '/^a/{delete a; c=0; p=1} 
      p{a[++c]=$0} 
     /^c/{for(k=1;k<=c;k++) print a[k]; exit}' file 

a2 - last match /a/ 
b 
c - first match /c/