为什么 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,之前很少使用它。我已经查阅了手册页和 Google,但我想我找错了地方...

编辑:我理解 awk 以行的形式处理文本流。我猜我的“print”只是按照 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仅在条件语句内设置,因此旧值会反复使用,直到下一次输入行与条件语句匹配。

相关内容