理解 awk 'NR%2 ...`

理解 awk 'NR%2 ...`

你好,我正在使用“Bash 命令行和 shell 脚本袖珍入门”来学习 bash,但我不明白 awk 的一章,其中说明了打印偶数行。

命令:

awk ' NR%2 { printf "%s", $0; print "" }' < data

内容数据文本文件:

a,b,c,d
e,f,g,h
1,2,3,4
5,6,7,8

输出:

a,b,c,d
1,2,3,4

我的问题是为什么它打印奇数行而不是偶数行?

我确实运行了 NR%2==1 和 NR%2==0 ,它按照预测给出了奇数/偶数输出。
我缺少什么?

答案1

NR是个以一为基础记录(行)号。NR % 2将其除以二并返回余数,因此奇数为 1,偶数为 0。在 awk 中,非零数字为真,因此将打印第一行、第三行等。

NR如果从零开始计算,情况会有所不同。

答案2

因为 1 算作“真”,0 算作“假”。因此,当NR % 2不为零时,将打印该行,因此您将得到奇数行作为输出。

答案3

您可能已经读过很多文字,其中告诉您,在 shell 脚本中 0 表示成功,1 表示失败。这绝对是真的。但是,awk 不是 shell, awk 是一个完全独立的工具,可以从 shell 脚本调用,并且 awk 不测试退出状态,它测试布尔条件,其中非零表示 true,0 表示 false,就像 C 和许多其他基于 Algol 的语言一样。

考虑一下这对这个 shell 脚本意味着什么:

$ foo=0; if [ $foo ]; then echo "success"; else echo "failure"; fi
success

或等效的:

$ foo=0; if test $foo; then echo "success"; else echo "failure"; fi
success

与这个 awk 脚本对比:

$ awk 'BEGIN{ foo=0; if ( foo ) print "true"; else print "false" }'
false

这两个脚本都在测试,0但在 shell 中,这是一个退出状态,意味着成功,而在 awk 中,这是一个意味着 false 的条件 - 2 个非常不同的事情。

在外壳中它是结果of [ $foo ](或test $foo),即对 中包含的退出状态执行[简写 for ,然后将其作为条件进行评估并发现为真。您可以通过编写以下内容在 awk 中实现相同的功能:testfooif

awk '
    function test(exit_status) { return (exit_status==0 ? 1 : 0) }
    BEGIN{ foo=0; if ( test(foo) ) print "true"; else print "false" }
'
true

你说I did run NR%2==1 and NR%2==0 and it gives me odd / even output as predicted.- 是的,因为 awk 1(或任何其他非零值)处于true条件上下文中,因此打印当前行,0而 false 则不打印当前行。

相关内容