この質問の目的のために一般的に作成された例として、私の意図は、ある数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
スタックに「物事をそのまま残す」ことに失敗します。
これは何が起こったのかについての正しい分析ですか?もしそうなら、これは仕様によるものですか? 基本的には、貪欲な繰り返しでバランシンググループを後戻りすると不均衡が生じる可能性があるため、これはバグとして分類される可能性があるためです (または、少なくとも文書化されていない驚くべき動作)。