2016-09-29 2 views
0

Регулярное выражение, например (?:(?=abc)|[abc])+, будет соответствовать строке, состоящей из a, b и c до тех пор, пока условие lookahead не будет выполнено. . для строки acbababcaaa она будет соответствовать acbab - останавливается прямо перед первым abc, хотя она может продвинуться до конца строки, если она была чрезмерно жадной.Поведение в голосе внутри группы повторного чередования

Мы можем сделать это, добавив $ в конец шаблона ((?:(?=abc)|[abc])+$) - теперь это фактически соответствует концу строки.

Когда мы сейчас изменим повторение на то, чтобы быть полезным ((?:(?=abc)|[abc])++$) - он будет соответствовать bcaaa - таким образом, первая позиция, где lookahead больше не может соответствовать.

Может ли кто-нибудь объяснить причины такого поведения?

+0

Первый будет соответствовать началу строки, если не используется глобальный режим поиска (см. [Demo] (https://regex101.com/r/t9zDtJ/1)), а не 'abcab'. –

+0

@ WiktorStribiżew Вы, очевидно, правы - у меня была неправильная строка в copy + paste. Обновлен вопрос. –

+0

Здесь я считаю, что в PCRE индекс не перемещается, когда у вас есть * совпадение нулевой ширины *. Просто обратите внимание, что поведение в JS отличается от того, что регулярное выражение JS заставляет индекс регулярного выражения продвигаться после совпадения нулевой ширины. В некоторых ситуациях это поведение замечательно (когда вы сопоставляете последовательные подстроки нулевой ширины и ненулевой ширины, и, как в этом случае, могут быть «глюки». В последнем примере для обладателя квантификатора требуется конец строки сразу после ответвления, поэтому все совпадения нулевой ширины не соответствуют совпадению, и вы получаете только последний кусок, не содержащий 'abc' –

ответ

1

Когда вы вынуждаете двигатель двигаться вперед, он больше не возвращается к первой группе (?:...).

После просмотра abc с этим положительным движком lookahead существует целая группа и ожидает окончания строки ввода $. Он не существует и не может отступить, чтобы попробовать другую сторону чередования, чтобы он полностью не прошел, и все предыдущие потребляемые символы [abc] освобождены, а указатель сбрасывается на следующий символ предыдущей начальной позиции всего шаблона.

Вы можете написать это атомной группой (?>(?=abc)|[abc])+$, чтобы более четко выразить разницу. Этот процесс продолжается, и он терпит неудачу, когда он видит abc в строке ввода, за которой не следует конец строки $.

Именно поэтому bcaaa символов сопоставляются в конце, потому что положительный прогноз никогда не произойдет после того, как a до bcaaa будет потребляться.

Смежные вопросы