Как обобщенный пример для этого вопроса, я намерен сопоставить некоторое количество a
', затем равное число b
', плюс еще один 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
, который использует жадное повторение в конструкции балансировочной группы, соответствует 3 a
и 3 b
's, что НЕ предназначено. r2
, который использует неохотное повторение, дает мне 2 a
и 3 b
's, что и есть.
Единственное, что я могу объяснить, это то, что когда (?<B-A> b)+
обращается к одному меньше b
, он появляется из стека b
, но НЕ отбрасывает то, что было соответствующим образом вытолкнуто из стека a
. Таким образом, хотя один менее b
теперь сопоставляется из-за обратного отслеживания, стек a
остается пустым. Это единственный способ объяснить, как r1
может соответствовать aaabbb
.
Обратите внимание, что использование неохотой +?
в r2
не вызывает этой проблемы. То, как я это вижу, это потому, что в отличие от жадного повторения, неохотное повторение не должно "отменить ущерб" стеку a
, так сказать. Напротив, жадное повторение вызывает как можно больший "ущерб", но откат не позволяет "оставить вещи такими, какие они есть" в стеке a
.
Это правильный анализ того, что произошло? И если да, то это поведение по дизайну? Потому что то, что в основном выглядит для меня, это то, что откат балансирующей группы в жадном повторении может привести к дисбалансу, и, таким образом, это потенциально может быть отнесено к категории ошибок (или, по крайней мере, несколько удивительного поведения, которое неадекватно документировано).