[Archlinux 上的 GNU awk v4.2.1]
抑制awk
从 cli 到 stdout 的默认打印操作很简单,并且在 UL 上有详细记录,例如这里。从脚本中执行此操作让我很头疼。这是玩具脚本:
#!/usr/bin/awk -f
BEGIN {FS=","}
FNR > 1 # skip header
{
if ( $1 == $2 ) {
if ( NR == 4 ) {
printf("*** Print NR=4 ok. \n")
} else {
print > "/dev/null" # print nothing
}
} else {
printf("=== Fields 1 and 2 not equal (NR=%s). \n",NR)
}
}
和玩具数据:
col1 col2
1,3
2,2
aa,aa
3.01,-353.01
4.1,4.1
101,101
hello, hello
asd,koi0
以及预期/期望的输出:
=== Fields 1 and 2 not equal (NR=2).
*** Print NR=4 ok.
=== Fields 1 and 2 not equal (NR=5).
=== Fields 1 and 2 not equal (NR=8).
=== Fields 1 and 2 not equal (NR=9).
相反,我得到:
=== Fields 1 and 2 not equal (NR=1).
1,3
=== Fields 1 and 2 not equal (NR=2).
2,2
aa,aa
*** Print NR=4 ok.
3.01,-353.01
=== Fields 1 and 2 not equal (NR=5).
4.1,4.1
101,101
hello, hello
=== Fields 1 and 2 not equal (NR=8).
asd,koi0
=== Fields 1 and 2 not equal (NR=9).
为了抑制输出到标准输出,我尝试使用:
getline
、 {}
、next
,printf("")
甚至使用奇怪的ORS=""; print ""; ORS="\n"
而不是print > "/dev/null"
。显然我在那个该死的脚本中做了一些非常错误的事情,并且找不到什么......
答案1
这仅有的错误是
FNR > 1 # skip header
{
应该是
FNR > 1 { # skip header
带有条件的代码块必须与条件在同一行开始。
你原来的剧本是什么实际上做是第一
FNR > 1
这将打印从第二行开始的所有行(当条件没有关联的代码块时,默认操作是在条件为 true 时打印当前记录,就像该块已为 true 一样{ print }
)。
然后它将后面的块应用到每个行(因为该块没有关联的条件)。
这不是 GNU 的特性awk
。所有的awk
实现都应该像这样。
至于脚本的其他部分:
} else {
print > "/dev/null" # print nothing
}
这可以删除,留下
#!/usr/bin/awk -f
BEGIN { FS = "," }
FNR > 1 {
if ( $1 == $2 ) {
if ( NR == 4 )
printf("*** Print NR=4 ok.\n")
} else
printf("=== Fields 1 and 2 not equal (NR=%s).\n", NR)
}
或者,
#!/usr/bin/awk -f
BEGIN { FS = "," }
FNR == 1 { next }
$1 == $2 && NR == 4 { printf("*** Print NR=4 ok.\n") }
$1 != $2 { printf("=== Fields 1 and 2 not equal (NR=%s).\n", NR) }