4

作为针对此问题的一般酿造示例,我的意图是匹配一些a's,然后匹配相同数量的b's,再加上一个 's b

检查此片段中展示的两种模式(也在 ideone.com 上):

var r1 = new Regex(@"(?xn)
   (?<A> a)+   (?<B-A> b)+    (?(A)(?!))   b
");
var r2 = new Regex(@"(?xn)
   (?<A> a)+   (?<B-A> b)+?   (?(A)(?!))   b
");

Console.WriteLine(r1.Match("aaabbb"));
// aaabbb

Console.WriteLine(r2.Match("aaabbb"));
// aabbb

请注意,两种模式的匹配存在差异。r1,它在平衡组构造上使用贪婪重复,匹配 3a和 3 b,这不是预期的。r2,它使用了不情愿的重复,给了我 2a和 3 b,这预期的。

我可以解释这一点的唯一方法是,当(?<B-A> b)+回溯匹配一个 lessb时,它会从B堆栈中弹出,但不会推回相应地从A堆栈中弹出的内容。因此,即使b现在由于回溯而匹配到少一个,A堆栈仍然是空的。这是我可以解释如何r1匹配的唯一方法aaabbb

请注意,使用不情愿+?inr2不会导致此问题。在我看来,这是因为与贪婪的重复不同,不情愿的重复不必“消除”对A堆栈的损害,可以这么说。相比之下,贪婪的重复会造成尽可能多的“损害”,但回溯无法“让事情保持原样”到A堆栈中。

这是对发生的事情的正确分析吗?如果是这样,这种行为是设计使然吗?因为在我看来基本上是在贪婪的重复中回溯平衡组可能会导致不平衡,因此这可能被归类为错误(或者至少是没有充分记录的有点令人惊讶的行为)。

4

1 回答 1

2

这是 Mono 中的一个错误

人们Environment.Version在 IdeOne 上获得类似 .NET 的原因是 Mono 要求向后兼容 .NET,包括与基于框架版本做出决策的应用程序的兼容性。

于 2012-03-12T22:27:57.593 回答