Perl - 后面的捕获组后不可用反向引用?

时间:2013-11-23 16:08:17

标签: regex perl backreference

当捕获组后跟一个问号时,反向引用似乎不可用

my $test = "this is a very long day indeed";

if ($test =~ m/^this.+(very).+(indeed)?/) {
  print "It matched the regex.\n";
  print "$1 :: $2\n";
}

打印

It matched the first test.
very :: 

这是正常行为吗?我在任何文档中都找不到它。我正在尝试匹配第二个捕获组可能存在或不存在的日志文件中的行。

2 个答案:

答案 0 :(得分:4)

这不是一个反向引用问题。最后一个组中的字符由.+匹配,但不与可选的捕获组匹配,因此最后一组匹配空字符串。

问题是您使用的贪婪量词匹配所有可能的字符。由于您的上一个组是可选的,.+匹配所有直到行的末尾,正则表达式引擎不需要回溯以匹配您的字符串(并且不需要找到“确实”)。

解决问题的一种简单方法是使用延迟量词而使用结束锚来强制转到行尾(因为惰性量词会尽快停止):

m/^this.+(very).+?(indeed)?$/

注意:如果“确实”并不总是字符串的最后一个字符,则必须在.*之前添加$

答案 1 :(得分:1)

这是一个关于贪婪的补充说明,这是你的问题(卡西米尔得到了回答)。

默认情况下,认识到正则表达式引擎会消耗掉所有能力,直到它找到满足当前评估子表达式右边的子表达式的内容。

任何时候你想使用一个.+贪婪的量词与DOT元数据都应该引发一个红旗三思而后行。如果可能的话,它会直接超过你想要的马赫。

出于这个原因,请尝试将其替换为无法通过预定目标的更具体的内容。

修改示例正则表达式会略微说明如何发生这种情况。

 my $test = "this is a very long day indeed, very long.";

 if ($test =~ m/

      ^
      ( this )               # (1)
      ( .+ )                 # (2)
      ( very )               # (3)
      ( .+ )                 # (4)
      ( indeed )?            # (5)

 /x) {
   print "All  = '$&'\n";
   print "grp1 = '$1'\n";
   print "grp1 = '$2'\n";
   print "grp1 = '$3'\n";
   print "grp1 = '$4'\n";
 }

 # Output >>
 # 
 # All  = 'this is a very long day indeed, very long.'
 # grp1 = 'this'
 # grp1 = ' is a very long day indeed, '
 # grp1 = 'very'
 # grp1 = ' long.'
 #