为什么在Perl正则表达式中*似乎不贪婪?

3
我原以为它会打印"[b]",但它实际打印的是"[]":
$x = "abc";
$x =~ /(b*)/;
print "[$1]";

如果把星号替换为加号,它的表现就符合我的期望了。难道加号和星号都应该是贪婪的吗?
添加:谢谢大家在几秒钟内指出(似乎如此!)“b *”匹配空字符串,其第一个出现在字符串开始之前。因此,贪婪性根本不是问题。它在甚至到达第一个'b'之前就匹配了空字符串。
6个回答

10

虽然它很贪心,但b*会匹配空字符串。anything*总是匹配空字符串,所以,

  "abc"
  /\
     --- matches the empty string here.
如果你打印$',你会看到它是"abc",这是匹配后剩下的字符串。贪婪只是意味着在"bbb"的情况下,你得到的是"bbb",而不是"b"或"bb"。

2
我明白了。所以贪婪模式并不是问题所在。它从一开始就匹配空字符串,因此根本没有机会贪婪地匹配 b 的字符串。 - dreeves

10

这个模式将匹配并返回第一次b*为true的时间,也就是它将在a处执行零宽度匹配。为了更清楚地说明发生了什么,请执行以下操作:

$x = "zabc";
$x =~ /(.b*)/;
print "[$1]";

3
正则表达式将匹配 a(backtrack)(由于正则表达式回溯,因此它是一个空值),并在那里结束。 由于有 + 限定符,它不匹配 ac,因此 $1 的值变为 b

1
不太正确。它匹配并终止于“a”,而不是“c”。 - chaos

3
正则表达式会在字符串中尽可能早地匹配。对于 'abc' =~ /(b*)/,它可以在字符串的开头匹配零个 b。如果你尝试匹配 'bbc',那么会输出:
[bb]

1

尽早匹配比匹配长度更重要(据我所知,这是Perl的正则表达式匹配引擎的情况,它是一个NFA)。因此,在字符串开头的零长度匹配比后面更长的匹配更可取。

有关更多信息,请在有关正则表达式匹配引擎的文章中搜索“DFA vs NFA”。


0

在模式结尾使用*几乎总不是你想要的。我们甚至在《学习Perl》中将其作为一个技巧问题,以说明这个问题。


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