awk逻辑条件混乱



谁能解释一下为什么这个工作是预期的:
echo "onentwonthreen" | awk '{if (gsub(/one/,"")) { print } else {print $0}}'


two
three

echo "onentwonthreen" | awk '{if (gsub(/four/,"")) { print } else {print $0}}'

one
two
three

但是这个没有?
echo "onentwonthreen" | awk '{if (gsub(/one/,"")) { print }}'


同样,如果试图链接多个替换,要求它们都返回发生替换的非零计数,然后只打印更改的结果,否则打印原始内容:
echo "onentwonthreen" | awk '{if (gsub(/one/,"") && gsub(/two/,"")) { print } else {print $0}}'

我得到了:


two
three

我期望的地方:


three

我在这里错过了什么?从任何其他编程语言来看,我希望这"只是工作"。请注意,我在BSD和GNU awk中观察到相同的行为。

编辑:

我认为这与awk处理多行输入的方式有关:

echo "onentwonthreen" | awk '{if (gsub(/one/,""))  print "found"; else print "not found"  }'
found
not found
not found
not found
printf 'onentwonthreen' | awk '{if (gsub(/one/,"")) { print }  else {print $0}}'

可以简化为:

printf 'onentwonthreen' | awk '{gsub(/one/,""); print}'

,因为它只是从每行删除one,如果存在,并打印每行。

另一方面,你失败的脚本:

printf 'onentwonthreen' | awk '{if (gsub(/one/,"")) { print }}'

可简化为:

printf 'onentwonthreen' | awk 'gsub(/one/,"") { print }'

从每行删除one(如果存在),但它只打印gsub()返回非零数字的行,即删除至少1个one

你发布的另一个脚本:

printf 'onentwonthreen' |
awk '{if (gsub(/one/,"") && gsub(/two/,"")) { print }  else {print $0}}'

可以简化为:

printf 'onentwonthreen' |
awk 'gsub(/one/,""){ gsub(/two/,"") } { print }'

所以它尝试删除ones和如果成功,则它试图删除twos(所以它永远不会试图删除没有onetwo在同一行,你的输入中没有任何情况),最后它打印每一行,不管发生了什么。

如果你想总是删除ones和twos并打印每一行,那么这将是:

printf 'onentwonthreen' |
awk '{gsub(/one/,""); gsub(/two/,""); print }'

好了,有两件事:

  1. 我需要解析输入,以便awk将其视为单个记录,通过添加BEGIN {FS="n"; RS=""}
  2. 我混淆了printprint $0的用法,认为前者存储修改后输入的当前值,而后者存储原始值,但它们都只存储当前值。

所以我最后一个问题的解决方案是:

echo "onentwonthreen" | awk 'BEGIN {FS="n"; RS=""}{orig=$0;if (gsub(/one/,"") && gsub(/two/,"")) { print }  else {print orig}}'

three

相关内容

  • 没有找到相关文章

最新更新