在 Awk 中,当我将正则表达式存储在变量中时,我可以在需要正则表达式的地方使用该变量吗?
Aho 的 AWK 编程语言 说
请注意,字符串匹配模式
/Asia/
是一个简写
$O ~ /Asia/
我有一个文本文件:
$ cat f1
line 1; li
ne
2
line 3
lin
e 4
为什么以下两种方式有效
$ awk -v pat='in' '{if (match($0, pat)) print $0; } ' f1
line 1; li
line 3
lin
$ awk -v pat='in' ' $0 ~ pat {print $0} ' f1
line 1; li
line 3
lin
而以下没有
$ awk -v pat='in' ' pat {print $0} ' f1
line 1; li
ne
2
line 3
lin
e 4
?
谢谢。
答案1
只有/foo/
单独是 的缩写$0 ~ /foo/
。
在... ~ /.../
or match(/.../, ...)
... 中,它只是正则表达式的某种形式的引用运算符,而在其他上下文中,它更多的是解析为数字(0 或 1)的运算符。
这种双重含义可能有点令人困惑。中存在很多双重含义/歧义awk
。
/foo/
根据是否与正则表达式$0
匹配而扩展为 1 或 0 foo
,但当恰好匹配时则"1" ~ /foo/
不是,这里不再缩写为。在或 的情况下,您会看到不同实现的行为有所不同。"1" ~ "1"
$0
foo
/foo/
($0 ~ /foo/)
"1" ~ (/foo/)
"1" ~ +/foo/
var
只是var
。
var
如果变量是数字或数字字符串并解析为非零数字,或者它是字符串并解析为非空字符串,则 as 条件表示 true。
用 声明的变量-v var=value
属于那些可能被视为数字字符串的变量,如果它们看起来像数字和字符串。
awk -v var=in 'var {print "x"}'
x
为每条记录打印,因为in
它看起来不像数字,也不是空字符串。
awk -v var=0 'var {print "x"}'
不会打印x
,同时:
awk 'BEGIN{var = "0"}; var {print "x"}'
将打印显式声明为字符串变量的x
每条记录。var
因此,尽管它看起来像一个数字,但它并不被视为数字。
这是双重含义中的另一种。根据上下文,变量可以被视为数字或字符串。另请参阅>
,根据上下文被视为比较运算符或重定向运算符(这又是几种不明确的情况,其中行为在实现之间有所不同)。
请注意,您还可以执行以下操作:
awk '{print /foo/ + /bar/}'
这与以下内容相同:
awk '{print ($0 ~ /foo/) + ($0 ~ /bar/)}'
但如果使用串联而不是+
awk '{print /foo/ /bar/}'
这不起作用,因为/RE/
运算符和/
除法运算符之间再次存在歧义。如有疑问,请使用括号:
awk '{print (/foo/) (/bar/)}'
顺便说一句,您应该避免使用-v
存储正则表达式或任何可能包含反斜杠的内容,因为 ANSI 转义序列在其中扩展(使用 GNU awk
4.2 或更高版本,以 开头@/
和结尾的值/
也是一个问题)。相反,您应该使用环境变量:
RE='\.txt$' awk '$0 ~ ENVIRON["RE"] {...}'
例如。