Есть ли реализация регулярных выражений в Python / PHP / JavaScript, которая поддерживает переменную длину lookbehind-assertion?
/(?<!foo.*)bar/
Как я могу написать регулярное выражение, имеющее то же значение, но не использующее lookbehind-assertion?
Есть ли вероятность, что этот тип утверждения будет реализован когда-нибудь?
Вещи намного лучше, чем я думал.
Обновить:
(1) Есть реализация регулярных выражений, которые уже поддерживают lookbehind-assert с переменной длиной.
Регулярный модуль Python (не стандартный re , но дополнительный модуль regex ) поддерживает такие утверждения (и имеет много других интересных функций).
>>> import regex >>> m = regex.search('(?<!foo.*)bar', 'f00bar') >>> print m.group() bar >>> m = regex.search('(?<!foo.*)bar', 'foobar') >>> print m None
Для меня было большим сюрпризом, что в регулярных выражениях есть что-то, что Perl не может сделать, и Python может. Возможно, для Perl существует также «расширенное регулярное выражение»?
(Спасибо и +1 MRAB).
(2) В современных регулярных выражениях есть классная функция \K
Эти символы означают, что когда вы делаете подстановку (и с моей точки зрения наиболее интересным вариантом использования утверждений является подстановка), все символы, найденные до \K не должны быть изменены.
s/unchanged-part\Kchanged-part/new-part/x
Это почти похоже на смотровое утверждение, но не настолько гибкое, конечно.
Подробнее о \K :
Насколько я понимаю, вы не можете использовать \ K дважды в одном и том же регулярном выражении. И вы не можете сказать, до какого момента вы хотите «убить» персонажей, которые вы нашли. Это всегда до начала линии.
(Спасибо и +1 к икегами).
Мои дополнительные вопросы:
\K ? regex для Python. В большинстве случаев вы можете избежать искажений переменной длины с помощью \K
s/(?<=foo.*)bar/moo/s;
было бы
s/foo.*\Kbar/moo/s;
Отрицательные взгляды немного сложнее.
s/(?<!foo.*)bar/moo/s;
было бы
s/^(?:(?!foo).)*\Kbar/moo/s;
потому что (?:(?!STRING).)* относится к STRING поскольку [^CHAR]* относится к CHAR .
Если вы просто соответствуете, вам может и не понадобиться \K
/foo.*bar/s /^(?:(?!foo).)*bar/s
Для Python существует реализация регулярного выражения, которая поддерживает переменные длины lookbehinds:
http://pypi.python.org/pypi/regex
Он предназначен для обратной совместимости со стандартным модулем re.
Вы можете изменить строку И шаблон и использовать переменную длину lookahead
(rab(?!\w*oof)\w*)
Соответствует полужирным шрифтам:
raboof rab7790oof raboo rabof rab rabo rabooof rabo
Исходное решение, насколько я знаю:
Джефф 'japhy' Pinyan
Отображаемое регулярное выражение найдет любой экземпляр bar которому не предшествует foo .
Простой альтернативой было бы сначала foo с строкой и найти индекс первого вхождения. Затем найдите bar и посмотрите, сможете ли вы найти событие, которое появляется перед этим индексом.
Если вы хотите найти экземпляры bar которым напрямую не предшествует foo , я мог бы также предоставить regexp для этого (без использования lookbehind), но это будет очень уродливо. В принципе, инвертируем смысл /foo/ – ie /[^f]oo|[^o]o|[^o]|$/ .
foo.*|(bar)
Если foo находится в первой строке, то регулярное выражение будет соответствовать, но групп не будет.
В противном случае он найдет bar и назначит ее группе.
Поэтому вы можете использовать это регулярное выражение и искать результаты в найденных группах:
>>> import re >>> m = re.search('foo.*|(bar)', 'f00bar') >>> if m: print(m.group(1)) bar >>> m = re.search('foo.*|(bar)', 'foobar') >>> if m: print(m.group(1)) None >>> m = re.search('foo.*|(bar)', 'fobas') >>> if m: print(m.group(1)) >>>
Источник.