2013-08-23 213 views
16

今天我在網上搜索一個命令,在一個模式後面打印下兩行,並且遇到了一個我無法理解的awk命令。解釋awk命令

$ /usr/xpg4/bin/awk '_&&_--;/PATTERN/{_=2}' input 

有人可以解釋嗎?

回答

2

奇妙的隱晦。時間允許時更新。

_正被用作變量名稱。 &&是一個邏輯運算符,它有兩個真正的動作一起運行。一旦_的值減小到零,則& &的後半部分爲假,並且不會生成輸出。

print -- " 
xxxxx 
yyyy 
PATTERN 
zzz 
aa 
bbb 
ccc 
ddd" | awk '_&&_--;/PATTERN/{_=2}' 

輸出

zzz 
aa 

調試版本

print -- " 
xxxxx 
yyyy 
PATTERN 
zzz 
aa 
bbb 
ccc 
ddd" | awk '_&&_--;{print "_="_;print _&&_};/PATTERN/{_=2;print "_="_ }' 

輸出

_= 
0 
_= 
0 
_= 
0 
_= 
0 
_=2 
zzz 
_=1 
1 
aa 
_=0 
0 
_=0 
0 
_=0 
0 
_=0 
0 
7

簡單地說,在給定的正則表達式表達式匹配不包含匹配的行之後,該命令會打印多行。

行數在塊{_=2}中指定,如果行匹配PATTERN,則變量_設置爲2。在匹配行之後讀取的每行都會導致_遞減。您可以讀取_&&_--,就好像_大於零,然後減1,這發生在匹配後的每一行,直到_達到零。當用n這類更明智的名稱替換變量_時,這非常簡單。

一個簡單的演示應該清楚(打印2行遵循匹配foo任何行):

$ cat file 
foo 
1 
2 
3 
foo 
a 
b 
c 

$ awk 'n && n--;/foo/{n=2}' file 
1 
2 
a 
b 

所以,當它被匹配與foo線則經過設置爲2 n只有真減少n並打印當前行。由於具有短路評價nawk僅減量時n爲True (N> 0)所以在這種情況下爲n唯一可能的值是2,1或0

awk有以下結構condition{block}和當條件評估爲True時,將對當前記錄執行塊。如果您不提供塊awk使用默認塊{print $0}所以n && n--;是沒有塊的條件,只有在正則表達式匹配後對n行計算爲True。分號只是爲條件n&&n--劃分條件/foo/明確表示該條件沒有阻止。

要打印下面的比賽,包括這場比賽,你會做兩行:

$ awk '/foo/{n=3} n && n--' file 
foo 
1 
2 
foo 
a 
b 

額外額外:所使用的/usr/xpg4/bin/awk完整路徑的事實告訴我,這段代碼的目的是爲Solaris機器作爲/usr/bin/awk是完全破碎,應該不惜一切代價避免。

+2

很好的解釋 – CBR

11

_在這裏被用作變量名(有效但顯然令人困惑)。如果你將它改寫爲:

awk 'x && x--; /PATTERN/ { x=2 }' input 

然後它更容易解析。每當匹配/PATTERN/時,變量將被設置爲2(並且不會輸出該行) - 這是下半部分。第一部分在x不爲零時觸發,並減少x以及打印當前行(缺省操作,因爲該子句未指定操作)。

最終結果是在模式匹配後立即打印兩條線,只要這兩條線都不匹配模式。

2

說明

awk詞語具有以下形式:

condition action; NEXT_EXPRESSION 

如果conditon爲真動作(一個或多個)將被執行。此外請注意,如果條件爲真,但操作已被省略,awk將執行print(默認操作)。

你在你的代碼的兩個表達式,將獲得在輸入​​的每一行執行:

_&&_--   ; 
/PATTERN/{_=2} 

兩者都是由一個;分開。正如我告訴,如果省略動作是默認操作print會發生一樣

_&&_-- {print}; 
/PATTERN/ {_=2} 

在您的例子_是一個變量名,它得到由0輸入的第一行初始化,在第一次使用之前 - 由awk自動執行。

第一個條件是(0) && (0) ..什麼結果是錯誤的,因爲0 && 0評估爲false而awk將不會打印。

如果找到該圖案,_將被設置爲2這使得第一條件的下一行是(2) && (2)下一行並(1) && (1)後的條件已被評估之後線_遞減。兩者都評估爲true,awk將打印這些行。

然而,不錯的益智;)

+0

輕微的錯誤,後遞減具有更高的順序或優先順序,因此邏輯與顯式爲'(0 && 0 - )'作爲'(0 && 0) - '計算爲-1。 –

+0

很高興知道..讓我以這種方式提升帖子。 – hek2mgl

+0

@sudo_O'awk'_ &&_--; 1 {printf「%i \ n」,_};/Pattern/{_ = 2}'input.txt'我不明白上面那行的輸出。如果遞減發生在符合awk文檔的地方,那麼右邊的'&&'在第一個測試中應該是1,在模式匹配之後在第二個測試中應該是0。所以我希望只打印一行。我在這裏錯過了什麼? – hek2mgl