强类型正则表达式常量如何在 GNU Awk 中工作?

How do strongly typed regexp constants work in GNU Awk?

强类型正则表达式常量是 GNU Awk 拥有的一个方便的工具。它记录在 GNU Awk User's Guide -> 6.1.2.2 Strongly Typed Regexp Constants 中,您可以在其中找到有趣的示例。

通过阅读它和对 的评论,我编了一些例子来说明这些:

$ cat file
he;llo
ho
are
you;
$ gawk -v patt='@/;/' '[=10=] ~ patt' file  # it prints those lines containing ";"
he;llo
you;

在这种情况下,我们传递模式“;”使用 @/;/ 所以它会打印所有包含“;”的行在他们里面。

现在我想更进一步,动态设置这个参数。例如,将其放在文件的第一行读取:

$ cat file
;
line2: hello;how
line3: are|you?
line4: i am;fine

但是,我无法将模式设置为$0中包含的字符串,我尝试了各种方法:

gawk 'NR==1 {f=@""[=12=]; next} [=12=] ~ f' file
gawk 'NR==1 {f=@[=12=]; next} [=12=] ~ f' file

但是他们都return语法错误:

gawk: cmd. line:1: NR==1 {f=@[=13=]; next} [=13=] ~ f
gawk: cmd. line:1:           ^ syntax error

在这种情况下,“;”被设置为要匹配的模式,我希望它从第 2 行开始处理正则表达式,从而匹配第 2 行和第 4 行,就好像我们会做 gawk 'NR==1 {f=@/;/; next} [=15=] ~ f' 一样。但是,我无法动态设置强类型正则表达式常量。

有办法吗?

wrt I cannot set the strongly typed regexp constant dynamically - 你可以用该语句中的任何其他字符串替换“强类型正则表达式”,它仍然是正确的,因为根据定义你不能动态设置常量,“constant”和“dynamic”是互斥的。

强类型 regexp 常量主要用于将文字 regexp 传递给用户定义的函数(您不能使用常规 regexp 常量):

$ awk 'function foo(x){print x, typeof(x)} BEGIN{foo(/bar/)}'
awk: cmd. line:1: warning: regexp constant for parameter #1 yields boolean value
0 number

$ awk 'function foo(x){print x, typeof(x)} BEGIN{foo("bar")}'
bar string

$ awk 'function foo(x){print x, typeof(x)} BEGIN{foo(@/bar/)}'
bar regexp

因此您不需要像使用动态正则表达式那样额外的转义层,因为 awk 在使用它之前不必先将表达式转换为正则表达式:

$ echo 'a.b a#b' | awk 'BEGIN{old="a\.b"; new="_"} {gsub(old,new)} 1'
awk: cmd. line:1: warning: escape sequence `\.' treated as plain `.'
_ _

$ echo 'a.b a#b' | awk 'BEGIN{old="a\.b"; new="_"} {gsub(old,new)} 1'
_ a#b

$ echo 'a.b a#b' | awk 'BEGIN{old=@/a\.b/; new="_"} {gsub(old,new)} 1'
_ a#b

你想用你问题中的例子做的是动态设置正则表达式,所以这需要一个动态的(即指定为字符串的)而不是常量正则表达式:

$ awk 'NR==1{f=[=12=]; next} [=12=] ~ f' file
line2: hello;how
line4: i am;fine