为什么Perl在使用*匹配组时会变得懒惰?

11
在Perl中,*通常是贪婪的,除非在它后面加上?。但是,当*用于一个组时,情况似乎不同。我的问题是“为什么”。考虑以下示例:
my $text = 'f fjfj ff';
my (@matches) = $text =~ m/((?:fj)*)/;
print "@matches\n";
# --> ""
@matches = $text =~ m/((?:fj)+)/;
print "@matches\n";
# --> "fjfj"

在第一个匹配中,Perl懒惰地什么也没有打印出来,虽然它本可以匹配到一些东西,正如第二个匹配所示。奇怪的是,当组的内容只是.而不是实际字符时,*的行为像预期的那样贪婪:

@matches = $text =~ m/((?:..)*)/;
print "@matches\n";
# --> 'f fjfj f'
  1. 注意:以上内容在Perl 5.12上进行测试。
  2. 注意:使用括号组内的捕获或非捕获括号都不会影响结果。

7
因为渴望比贪婪更重要。 - tchrist
@tchrist 这是一个很好的表述方式 :) - hobbs
2个回答

15

这不是贪婪或懒惰重复的问题。(?:fj)* 会尽可能多地匹配 "fj" 的重复,但它可以成功地匹配零次。当你尝试将其与字符串"f fjfj ff"匹配时,它将首先尝试在位置零(第一个“f”之前)进行匹配。你可以在位置零成功地匹配“fj”的最大次数为零,因此模式成功地匹配了空字符串。由于模式在位置零成功匹配,我们完成了匹配,引擎没有理由尝试后续位置的匹配。

故事的寓意是:不要编写可以匹配空内容的模式,除非你想让它匹配空内容。


7

Perl会尽早在字符串中匹配(最左边)。它可以通过在字符串开头匹配零次fj来进行第一次匹配。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接