答案1
该BEGIN
块在处理任何输入之前运行,因此$0
尚未初始化。
该END
块不会对 执行任何操作$0
,从而保留其最后的值。在 AWK 脚本中,这只是读取的最后一行,因为 AWK 逐行读取其所有输入,执行通常的字段分割处理(分配$0
等),但永远找不到匹配的块;但例如
seq 42 | awk '{ $0 = "21" } END { print }'
输出 21,而不是 42,因此不是“当END
块运行时加载最后一行$0
”的情况。
这没有记录在gawk(1)
联机帮助页,但它记录在mawk(1)
(显然对于 AWK 的实现):
类似地,在进入操作时
END
,$0
、 、 和 字段NF
的值与最后一条记录相比保持不变。
GNU AWK 手册确实提及这种行为:
事实上,所有 BWK
awk
、mawk
、 和gawk
都保留 的值以供在规则$0
中使用。END
“BWK awk
” 是 Brian Kernighanawk
的“一个真实的awk
”;它在 2005 年实施了这种行为,如其FIXES
文件中所述:
2005 年 4 月 24 日:进行修改
lib.c
,以便将$0
et al 的值保留在 END 块中,显然是按照 posix 的要求。感谢 havard eidnes 提供的报告和代码。
这种变化可见于“一个真实的awk
”历史。最新版本的 BWK 的awk
行为方式与 GNU AWK 相同:
$ echo three fields here | ./awk '{ $0 = "one" } END { print $0 " " NF }'
one 1
$ echo three fields here | ./awk 'END { $0 = "one"; print $0 " " NF }'
one 1
答案2
根据GNU awk 手册,有点不清楚$0
END 规则中应包含什么内容。 POSIX 要求NF
“应保留[其]价值”(*),但没有提及$0
.
最有可能的是由于疏忽,该标准并没有说它
$0
也被保留,尽管从逻辑上讲人们会认为它应该被保留。事实上,所有 BWK awk、mawk 和 gawk 都保留 的值$0
以供在END
规则中使用。但请注意,一些其他实现和许多旧版本的 Unix awk 不支持。
从某种意义上说,我认为这种行为是合乎逻辑的。如有必要,离开$0
该END
块可以轻松访问最后一条记录。第一条记录很容易访问,NR == 1 {...}
因此不需要特殊的关键字。另一方面, BEGIN
在加载第一条记录之前执行块允许设置FS
或RS
及时让它们对于第一条记录是活动的。
(* 无论这意味着什么,请参阅评论。)