この質問の目的のために一般的に作成された例として、私の意図は、ある数aの 、次に同じ数bの 、さらにもう 1 つの に一致させることbです。
このスニペットに示されている 2 つのパターンを調べます (これも 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
2 つのパターンの一致には違いがあることに注意してください。r1は、バランシング グループ コンストラクトで貪欲な繰り返しを使用し、3aと 3に一致しますbが、これは意図したとおりではありません。r2しぶしぶ繰り返しを使用する は、2aと 3を与えますがb、これは意図したとおりです。
これを説明できる唯一の方法は、(?<B-A> b)+バックトラックが 1 つ少ない に一致する場合b、スタックからポップしBますが、対応してスタックからポップされたものをプッシュバックしないAということです。したがって、bバックトラッキングにより 1 つ少なく一致したとしても、Aスタックは空のままです。r1これは、どのように一致するかを説明できる唯一の方法ですaaabbb。
reluctant +?inを使用しr2てもこの問題は発生しないことに注意してください。A私の見方では、貪欲な繰り返しとは異なり、消極的な繰り返しは、いわばスタックへの「ダメージを元に戻す」必要がないためです。対照的に、貪欲な繰り返しは可能な限り多くの「ダメージ」を引き起こしますが、バックトラックはAスタックに「物事をそのまま残す」ことに失敗します。
これは何が起こったのかについての正しい分析ですか?もしそうなら、これは仕様によるものですか? 基本的には、貪欲な繰り返しでバランシンググループを後戻りすると不均衡が生じる可能性があるため、これはバグとして分類される可能性があるためです (または、少なくとも文書化されていない驚くべき動作)。