我有一个名为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/
它完美地工作!因此,正则表达式似乎还不错,但是由于某种原因,将其放入变量中并针对该变量进行测试失败。这是为什么?什么会解决?显然,正则表达式可以保存到变量中,但是这个正则表达式有什么问题?
答案 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
,但是应该很容易看到如何修改或扩展它以执行更多或不同的事情。
请注意我们如何在单个正则表达式中使用单个|
进行替换。