Странное поведение негативного взгляда в будущее

У меня есть следующая строка: "text before AB000CD000CD text after", Я хочу сопоставить текст из AB с первым появлением CD. Вдохновленный этим ответом, я создал следующий шаблон регулярных выражений:

AB((?!CD).)*CD

Я проверил результат в https://regex101.com/ и вывод:

Full match  12-19   `AB000CD`
Group 1.    16-17   `0`

Похоже, он делает то, что мне нужно. Однако я не понимаю, почему это работает. Насколько я понимаю, мой шаблон должен сначала соответствовать AB, затем любому символу, за которым не следует CD, а затем самому CD. Но следуя этой логике, результат должен включать не 000, а только 00, потому что за последним нулем фактически следует CD. Мое объяснение неверно?

1 ответ

Решение

AB((?!CD).)*CD Матчи AB, то любой символ , который не запускается CD последовательность символов, а затем CD, Вот где вы ошибаетесь, говоря: "за этим не следует CD". Обратите внимание, что отрицательный прогноз находится перед .,

Кроме того, нет смысла использовать закаленный жадный жетон, когда отрицательная часть совпадает с задней границей, просто используйте ленивый шаблон сопоставления точек, AB(.*?)CD, Вам нужно использовать конструкцию, когда вы не хотите соответствовать AB (начальная граница) между AB а также CD т.е. AB((?:(?!AB).)*?)CD (это самый распространенный вариант использования).

Смотрите ссылку на rexegg.com о том, когда его использовать:

Предположим, наш босс теперь говорит нам, что мы все еще хотим соответствовать {END}, но мы также должны избегать {MID} раздел, если он существует. Начиная с ленивой версии "точка-звезда", чтобы обеспечить соответствие {END} разделитель, мы можем затем закалить точку, чтобы она не перевернулась {MID}:

{START}(?:(?!{MID}).)*?{END}

Если нужно избегать большего количества фраз, мы просто добавляем их к нашей закаленной точке:

{START}(?:(?!{MID})(?!{RESTART}).)*?{END}

Также смотрите эту ветку.

Другие вопросы по тегам