Я получаю неожиданный откат квантификатора +
регулярного выражения Raku.
В этом регулярном выражении:
'abc' ~~ m/(\w+) {say $0} <?{ $0.substr(*-1) eq 'b' }>/;
say $0;
Получаю ожидаемый результат:
「abc」 # inner say
「ab」 # inner say
「ab」 # final say
То есть квантификатор (жадный) +
получает все буквы, а затем условие не выполняется. После этого он начинает поиск с возвратом, освобождая последнюю полученную букву, пока условие не станет истинным.
Однако обратное отслеживание, похоже, не работает таким же образом, когда я помещаю квантификатор за пределы группы захвата:
'abc' ~~ m/[(\w)]+ {say $0} <?{ $0.tail eq 'b' }>/;
say $0;
Результат:
[「a」 「b」 「c」] # inner say
[「a」 「b」 「c」] # why this extra inner say? Shouldn't this backtrack to [「a」 「b」]?
[「a」 「b」 「c」] # why this extra inner say? Shouldn't this backtrack to [「a」 「b」]?
[「b」 「c」] # Since we could not successfully backtrack, We go on matching by increasing the position
[「b」 「c」] # Previous conditional fails. We get this extra inner say
[「c」] # Since we could not successfully backtrack, We go on matching by increasing the position
Nil # final say, no match because we could not find a final 'b'
Ожидается ли такое поведение? Если да, то почему они работают по-другому? Можно ли имитировать первое регулярное выражение, но при этом сохранить квантификатор вне группы захвата?
ПРИМЕЧАНИЕ.
Использование ленивого квантификатора «решает» проблему ... Это ожидаемо, потому что разница, похоже, возникает при возврате, а этого не происходит с ленивым квантификатором.
'abc' ~~ m/[(\w)]+? {say $0} <?{ $0.tail eq 'b' }>/;
[「a」]
[「a」 「b」]
[「a」 「b」]
Однако по соображениям производительности я бы предпочел использовать жадный квантификатор (пример в этом вопросе является упрощением).
([\w+])
и([\w])+
имитируют их неквадратные скобки, содержащие их аналоги. - person jubilatious1   schedule 10.12.2020