为什么正则表达式引擎没有回溯。*?

时间:2014-02-09 14:47:47

标签: regex linux perl backtracking nfa

我试图理解以下正则表达式:
拥有:

SRC=array.c builtin.c eval.c field.c gawkmisc.c io.c main.c \  
            missing.c msg.c node.c re.c version.c

作为多行文本,以下正则表达式无法匹配:

~$ perl -e '  
my $var = "SRC=array.c builtin.c eval.c field.c gawkmisc.c io.c main.c \  
missing.c msg.c node.c re.c version.c";  
$var =~ /^\w+=(.*(\\\n.*))/;  
print "$1\n";  

但我不确定为什么 我的意思是.*将匹配到行尾(\n)。然后由于.无法匹配该行的结尾,因此匹配失败。然后由于*是可选的,因此正则表达式引擎不应该回溯并释放\并尝试再次匹配?
由于后引用为空,这似乎不会发生 有人可以帮我理解这个吗?

2 个答案:

答案 0 :(得分:5)

编辑以考虑@amon的评论(顺便说一句,谢谢你)

您的作业声明......

my $var = "SRC=array.c builtin.c eval.c field.c gawkmisc.c io.c main.c \  
missing.c msg.c node.c re.c version.c";

...包含反斜杠后跟换行符。反斜杠在双引号中包含的字符串中使用时,用于转义紧跟在后的字符。如果您在此作业后立即打印$var,则会发现您的字符串中确实没有反斜杠。

您可以使用两种方法让正则表达式执行您希望它执行的操作。

选项1 - 保留双引号分配,但从正则表达式中删除反斜杠。

perl -e 'my $var = "SRC=array.c builtin.c eval.c field.c gawkmisc.c io.c main.c \  
missing.c msg.c node.c re.c version.c";  
$var =~ /^\w+=(.*(\n.*))/;  
print "$1\n";'

这很有效。

选项2 - 将您的作业语句放在单引号中,明确表示您想要 $var中的反斜杠:

# myfile.pl
my $var = 'SRC=array.c builtin.c eval.c field.c gawkmisc.c io.c main.c \  
missing.c msg.c node.c re.c version.c';  
$var =~ /^\w+=(.*(\\\n.*))/;  
print "$1\n";

因为我们的代码中有单引号,所以在perl -e内运行它会更简单。

> perl myfile.pl

这也有效。

所以,实际上,问题与回溯和.*没有太大关系。它与您在字符串中使用反斜杠以及您期望使用的结果有关。

答案 1 :(得分:0)

使用(\\\n.*),您需要一个反斜杠,后跟一个换行符,后跟零个或多个任何字符。

字符串中没有反斜杠,因此您的模式无法匹配。