为什么将我的正则表达式存储在变量中会破坏比较测试? (Awk / Gawk)

时间:2019-04-17 04:20:46

标签: bash awk

我有一个名为regeces的文件,其中包含许多逐行的正则表达式。这是一个示例:

The .* is .* years old
I like .* with lots of .*

我还有一个非常有创意的数据文件,名为data

The car is 3 years old
I like pizza with lots of pepperoni
I like tacos with lots of cheese
The house is 10 years old
A non-matching line
The couch is 5 years old
I like customers with lots of money
This line does not match

虽然肯定不是用狭义的方式编写正则表达式,但是它们足以匹配data的第五行和最后一行,并解释了我的问题。现在,这是我的程序:

#!/usr/bin/awk -f

BEGIN {
        while ("cat regeces" | getline)
                {
                reg = "/" $0 "/||" reg
                }
    sub(/\|\|$/, "", reg)
    print reg
    }

# $0 ~ /I like .* with lots of .* /||/The .* is .* years old/ {
$0 ~ reg {
    print $0
    }

因此,在BEGIN部分中,它读取regeces,构建一个正则表达式,并将其保存到变量中。作为故障排除工具,它也会打印出来。在主体中,它将每行与保存在变量中的正则表达式进行比较。带注释的行是为了方便测试问题。

存储在reg中的正则表达式为:

/I like .* with lots of .* /||/The .* is .* years old/

现在,如果我按编写的方式运行程序,它将输出每一行;也就是说,它不能排除data的第五行和最后一行。但是,如果我使用上述正则表达式并将程序的比较测试替换为:

$0 ~ /I like .* with lots of .* /||/The .* is .* years old/

它完美地工作!因此,正则表达式似乎还不错,但是由于某种原因,将其放入变量中并针对该变量进行测试失败。这是为什么?什么会解决?显然,正则表达式可以保存到变量中,但是这个正则表达式有什么问题?

1 个答案:

答案 0 :(得分:3)

您要在正则表达式中添加文字斜杠,因此您需要匹配的文本周围包含斜杠。

在Awk本身的语法中,正则表达式使用斜杠;但是您尝试匹配的这些正则表达式只是字符串。比较:

awk 'BEGIN { var = "^hello$" }
    $0 ~ var
    /^hello$/' <<<$'hello\ngoodbye'

将两次打印hello,因为两个匹配项是相同的。

以下是脚本的重大重构版本:

awk 'NR==FNR { r = (NR>1 ? r "|" : "") $0; next }
    $0 ~ r' regeces data

这只是重新实现grep,但是应该很容易看到如何修改或扩展它以执行更多或不同的事情。

请注意我们如何在单个正则表达式中使用单个|进行替换。