Странное поведение негативного взгляда в будущее
У меня есть следующая строка: "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}
Также смотрите эту ветку.