Они называются lookarounds; они позволяют вам утверждать, соответствует шаблон или нет, фактически не делая соответствие. Есть 4 основных подхода:
- Положительные отзывы: посмотрим, МОЖЕМ ли мы соответствовать
pattern
...
(?=pattern)
- ... до вправо от текущей позиции (взгляд вперед )
(?<=pattern)
- ... * влево текущей позиции (посмотрите позади )
- Негативные обходные пути - посмотрим, не сможем ли мы сопоставить
pattern
(?!pattern)
- ... до вправо
(?<!pattern)
- ... до влево
1036 **
Как простое напоминание, для поиска:
=
равно положительно , !
равно отрицательно
<
это взгляд позади , в противном случае это взгляд впереди
Ссылки
Но зачем использовать lookarounds?
Можно утверждать, что обходные пути в приведенном выше шаблоне не нужны, и #([^#]+)#
прекрасно справится с задачей (извлекая строку, захваченную \1
, чтобы получить не #
).
Не совсем. Разница заключается в том, что поскольку обходной путь не соответствует #
, он может быть снова «использован» при следующей попытке найти совпадение. Проще говоря, обходные пути позволяют перекрывать "совпадения".
Рассмотрим следующую входную строку:
and #one# and #two# and #three#four#
Теперь #([a-z]+)#
даст следующие совпадения (, как видно на rubular.com ):
and #one# and #two# and #three#four#
\___/ \___/ \_____/
Сравните это с (?<=#)[a-z]+(?=#)
, что соответствует:
and #one# and #two# and #three#four#
\_/ \_/ \___/ \__/
К сожалению, это не может быть продемонстрировано на rubular.com, так как он не поддерживает просмотр назад. Тем не менее, он поддерживает прогнозирование, поэтому мы можем сделать что-то похожее с #([a-z]+)(?=#)
, что соответствует ( как видно на rubular.com ):
and #one# and #two# and #three#four#
\__/ \__/ \____/\___/
Ссылки