你好,我正在使用“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 中实现相同的功能:test
foo
if
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 则不打印当前行。