为什么使用 gawk 时不能在 ~ 运算符的左侧放置正则表达式?
例如,给定以下文件,其中字段由制表符 (\t) 分隔:
$ cat cats
siberian 1970 73 2500
shorthair 1999 60 3000
longhair 1998 102 9859
scottish 2001 30 6000
如果我使用 gawk 查找记录,它会起作用:
$ gawk '$1 ~ /h/' cats
shorthair 1999 60 3000
longhair 1998 102 9859
scottish 2001 30 6000
但是,如果我移动操作数 $1 和 /h/ ,它不会:
$ gawk '/h/ ~ $1' cats
gawk: cmd. line:1: warning: regular expression on left of `~' or `!~' operator
~ 运算符的 gawk 手册页显示:
正则表达式匹配,否定匹配。注意:不要在 ~ 或 !~ 的左侧使用常量正则表达式 (/foo/)。仅在右侧使用。表达式 /foo/ ~ exp 与 (($0 ~ /foo/) ~ exp) 具有相同的含义。这通常不是预期的。
我不明白表达式 /foo/ 是如何被评估为 ($0 ~ /foo/) 的,而且这似乎只意味着较弱的短语“如果你在左边放置一个常量正则表达式,就会发生坏事”,但它并没有实际上并不意味着“如果将常量正则表达式放在左侧,则 gawk 的行为是未定义的,因为它没有被编程为以这种方式使用”。
我基本上不明白运算符 ~ 内部是如何评估的。
答案1
引用 awk 的 POSIX 规范:
~
当 ERE 标记在除or运算符右侧!~
或下述内置函数参数之一之外的任何上下文中显示为表达式时,结果表达式的值应等效于:
$0 ~ /ere/
这(与默认为 的操作相结合{ print }
)就是为什么您可以通过执行 来用作替代awk
品。grep
awk '/b/' <file
所以,答案只是“它被定义为以这种方式工作”。 /ere/
被定义为$0 ~ /ere/
除非在某些情况下,并且/ere/ ~ $1
不是特殊情况之一,因此它被评估为($0 ~ /ere/) ~ $1
。