Какая техническая причина для того, чтобы «утверждение за кадром ДОЛЖНО быть фиксированной длины» в регулярном выражении? - PullRequest
37 голосов
/ 26 сентября 2010

Например, приведенное ниже регулярное выражение приведет к сообщению о сбое утверждение просмотра позади не имеет фиксированной длины :

#(?<!(?:(?:src)|(?:href))=["\']?)((?:https?|ftp)://[^\s\'"<>()]+)#S

Подобного ограничения не существует для lookahead.

Ответы [ 5 ]

65 голосов
/ 26 сентября 2010

Взгляд вперед и взгляд назад далеко не так похожи, как подразумевают их имена. Выражение предпросмотра работает точно так же, как если бы оно было автономным регулярным выражением, за исключением того, что оно привязано к текущей позиции совпадения и не потребляет то, что соответствует.

Взгляд за спиной - это совсем другая история. Начиная с текущей позиции совпадения, он шагает назад по тексту по одному символу за раз, пытаясь сопоставить его выражение в каждой позиции. В случаях, когда совпадение невозможно, взгляд должен пройти весь путь до начала текста (один символ за раз, помните), прежде чем он сдастся. Сравните это с предварительным выражением, которое применяется ровно один раз.

Это, конечно, грубое упрощение, и не все ароматы работают таким образом, но вы понимаете. То, как применяются взгляды, принципиально отличается от (и намного, намного менее эффективно, чем) того, как применяются взгляды. Имеет смысл лишь ограничить, насколько далеко назад должен смотреть взгляд.

9 голосов
/ 26 сентября 2010

Прежде всего, это не так для всех библиотек регулярных выражений (например, .NET).

Для PCRE причина выглядит следующим образом:

Реализация вида назад утверждения, для каждой альтернативы, временно переместить ток Положение назад на фиксированную ширину и затем попробуйте сопоставить.

(по крайней мере, согласно http://www.autoitscript.com/autoit3/pcrepattern.html).

5 голосов
/ 17 октября 2016

PCRE не поддерживает плавающий вид сзади, потому что это может вызвать серьезные проблемы с производительностью. Это происходит из-за отсутствия возможности сопоставления справа налево: PCRE может запустить ветвь только с фиксированного левого угла, но левое положение с переменной длиной не может быть исправлено.

Как правило, старайтесь по возможности разветвлять свою деталь взгляда за фиксированную длину. Например вместо:

(?<=(src|href)=")etc.

(1) используйте это:

(?:(?<=src=")|(?<=href="))etc.

(2) Или с \K:

(src|href)="\Ketc.

Обратите внимание, что \K не является реальным взглядом сзади, потому что он всегда начинает поиск в конце предыдущего соответствия (без потенциального возврата в предыдущее соответствие).

(3) В некоторых сложных случаях только для просмотра назад вы можете осуществлять поиск с помощью «перевернутого» выражения предпросмотра в обратной строке. Не слишком элегантно, но работает:

.cte(?="=(ferh|crs))
2 голосов
/ 30 января 2015

У меня была такая же проблема, и я исправил ее с помощью (?: subexpression)

Определяет группу без захвата. такие как Write(?:Line)? "WriteLine" в "Console.WriteLine ()" "Запись" в "Console.Write (значение)"

Мне пришлось изменить регулярное выражение ниже, которое, как предполагается, должно ловить до , или что-то в начале строки, что давало мне утверждение lookbehind не фиксированной длины .

(?<=,|^)

с этим,

(?:(?<=,)|^)
0 голосов
/ 11 декабря 2017
grep -P '(?<=((three)|(one)) )two' <<< "one two three three two one"
grep: lookbehind assertion is not fixed length

grep -P '((?<=(three) )|(?<=(one) ))two' <<< "one two three three two one"
one two three three two one
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...