作为针对此问题的一般酿造示例,我的意图是匹配一些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
堆栈中。
这是对发生的事情的正确分析吗?如果是这样,这种行为是设计使然吗?因为在我看来基本上是在贪婪的重复中回溯平衡组可能会导致不平衡,因此这可能被归类为错误(或者至少是没有充分记录的有点令人惊讶的行为)。