我有一个名为的文本文件junk.txt
:
hello
foo
0
-1
0
1
0
2
0
foo
Cindy
00000
Lou
2 000
0
Who
0000
0
wat?
0000 00000
0
0
0000 00000
filler
00
0
00
000
0000
0
0
bye
当我运行以下命令时,我得到:
cat junk.txt | awk '{if (/foo/ ~ $1) print $1,"<-- found match"; else print $1}'
awk: cmd. line:1: warning: regular expression on left of `~' or `!~' operator
hello
foo
0 <-- found match
-1
0 <-- found match
1
0 <-- found match
2
0 <-- found match
foo
<-- found match
Cindy
00000
<-- found match
Lou
2
0 <-- found match
Who
0000
0
wat?
0000
0
0
0000
<-- found match
filler
<-- found match
00
<-- found match
0 <-- found match
00 <-- found match
000 <-- found match
0000 <-- found match
0 <-- found match
<-- found match
0 <-- found match
bye
我明白当正则表达式位于 的左侧时会发生什么~
。
我知道一个0
或一个空字符串(null?)将被视为匹配。
我不明白的是为什么有时 a 0
will 匹配,有时则不匹配。看起来它与之前处理的任何记录有关,但我认为awk
独立处理每个输入记录,因此它们不应该相互影响(至少在没有一些变量分配或其他操作的情况下)。
编辑:如果重要的话我正在使用 GNU Awk 4.1.3
答案1
来自 (g)awks 手册页:
~ !~ Regular expression match, negated match. NOTE: Do not use a constant regular expression (/foo/)
on the left-hand side of a ~ or !~. Only use one on the right-hand side. The expression /foo/ ~
exp has the same meaning as (($0 ~ /foo/) ~ exp). This is usually not what you want.
如果您以明确告诉您不要的方式使用它,您预计会发生什么?
答案2
事实上,这是一个有趣的问题。 @tink 指出了为什么你的代码不能按预期工作,但这不是问题。问题是“为什么0
有时会匹配”。
如果(/foo/ ~ $1)
确实意味着(($0 ~ /foo/) ~ $1)
,($0 ~ /foo/)
则将评估1
该行是否包含foo
,0
否则。因此,您(主要)正在评估0 ~ $1
.如果输入行为空,则$1 == ""
、 和空正则表达式始终匹配。如果输入行恰好为0
,则$1
和 也0 ~ 0
为 true。000
例如,如果输入行是,那么 也是$1
,并且0 ~ 000
不应该为真。但是,很可能会在检查匹配之前将其000
转换为。0
但不幸的是,这个解释并没有涵盖所有情况。
情况1
0 <-- found match
a
0 <-- found match
0 <-- found match
这完全符合预期。
案例2
0 <-- found match
00 00 <-- found match
0 <-- found match
这也是预期的,只要任意数量的零都被解释为0
。但现在,这个:
案例3
0 <-- found match
a
00 0
0
这不能这么简单地解释掉。匹配失败后,似乎不会发生到零的转换,并且后面应该匹配的行也不会发生。
案例4
0 <-- found match
a
00 00
a
0 <-- found match
无论发生什么,另一次失败的匹配似乎会将awk
的行为重置为正常,并且匹配再次按预期进行。
总而言之,GNU 手册页中的解释(awk
顺便说一下,它不是信息页的一部分)是不正确的(或者至少是不完整的),或者程序包含错误。