為什麼 awk 多次印出這一行?

為什麼 awk 多次印出這一行?

我有以下 ldif:

dn: cn=Robert Smith,ou=people,dc=example,dc=com
objectclass: inetOrgPerson
cn: Robert Smith
cn: Robert J Smith
cn: bob  smith
sn: smith
uid: rjsmith
userpassword: rJsmitH
carlicense: HISCAR 123
homephone: 555-111-2222
mail: [email protected]
alias: [email protected]
alias: [email protected]
description: nice hair
ou: Human Resources

dn: cn=John Doe,ou=people,dc=example,dc=com
objectclass: inetOrgPerson
cn: John Doe
cn: John Walker Doe
cn: Johnny
sn: Doe
uid: jdoe
userpassword: topsecret
carlicense: AKAHH 123
homephone: 123-458-362
mail: [email protected]
alias: [email protected]
alias: [email protected]
description: cool guy
ou: Sales

現在我正在針對它運行 awk 命令:

awk '/^mail:/ { mail = $2 }; {print mail };' ldif

預期結果是:

[email protected]
[email protected]

實際結果是:

[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]

我真的不明白為什麼 awk 多次給出這個輸出。如果有人能向我解釋它,我將非常感激,因為我是 awk 的新手,以前沒有使用過它。我已經查閱了手冊頁和谷歌,但我想我在那裡尋找錯誤的東西...

編輯:我知道 awk 成行處理文字流。我想我的“列印”只是按照 ldif 檔案中的行數列印輸出。但我怎麼才能阻止 awk 這樣做呢?我只想將每個結果列印一次..

答案1

此條件/^mail:/不會影響後面的所有指令,只會影響第一個指令 ( mail = $2)。

結果,第二條指令(print mail)被執行對於每一行

這就是為什麼在輸出的開頭實際上有一些空白行(mail尚未設定)。

其中任何一個都可以:

awk '/^mail:/ { { mail=$2 }; {print mail } };' ldif

awk '/^mail:/ { mail=$2; print mail };' ldif

就我個人而言,我更喜歡:

awk '/^mail:/ { print $2 }' ldif

答案2

@Dennis 提供了一個提供正確語法的解決方案,但沒有完全回答最初的問題“為什麼 awk 多次打印這一行?”

awk 在面向行的循環中運行,除了一些小的例外(例如 BEGIN 和 END)之外,它在每一行輸入上運行整個腳本。在OP的範例中,針對輸入檔的每一行執行以下偽代碼:

if LINE starts with "mail:"
    set MAIL to value of second field of the input record
endif

print MAIL

輸出重複行的原因是 print 語句是外部條件語句,因此執行每一個輸入行,而不僅僅是與正規表示式相符的行。此外,由於mail變數僅在條件語句內設置,因此舊值會一遍又一遍地重複使用,直到下一次輸入行與條件語句匹配為止。

相關內容