Lookbehind переменной длины не работает в файле perl, но работает в однострочном режиме

Если я помещу s/(?<!(?:href|src)=.{0,40})jpg//g в файл Perl и попытаюсь запустить его, он выдаст предупреждение: Variable length lookbehind is experimental in regex; marked by и завершится ошибкой.

Но если добавить однострочник perl, он будет работать успешно, хотя все равно будет предупрежден о Variable length lookbehind is experimental in regex; marked by.

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

Обновление: я использую perl 5.31.3


person jonah_w    schedule 31.10.2020    source источник
comment
Это сообщение является предупреждением, оно не должно приводить к сбою. Либо вы включили фатальные предупреждения в своем скрипте, либо проблема на самом деле кроется в другом.   -  person hobbs    schedule 31.10.2020
comment
Я действительно включил фатальное предупреждение. После того, как я изменил его на use warnings; или, как указал Виктор Стрибижев, добавил no warnings qw(experimental::vlb);, он может успешно работать.   -  person jonah_w    schedule 31.10.2020


Ответы (2)


До версии 5.30 положительный просмотр назад с неопределенным шаблоном переменной ширины не компилировался с ошибкой Variable length lookbehind not implemented.

В версии 5.30 вы разрешено использовать ретроспективный шаблон, который может соответствовать до 255 символов.

Использование обратного просмотра (например, (?<=foo?) или (?<!ba{1,9}r) ранее приводило к ошибке и отказу от компиляции. Теперь он компилируется (если максимальный просмотр назад составляет не более 255 символов), но вызывает предупреждение в новой категории предупреждений experimental::vlb. Это должно вас предупредить. что точное поведение может быть изменено на основе отзывов об использовании в полевых условиях.

Если вы используете (?<=WORD\s+), вы получите ошибку Lookbehind longer than 255 not implemented, поскольку обработчик регулярных выражений должен заранее знать, что длина подшаблона не будет длиннее 255, а квантификатор + имеет неопределенную длину. Итак, (?<=WORD\s{0,255}) будет работать.

В вашем случае вы знаете, что ваш шаблон просмотра назад никогда не будет соответствовать более чем 255 символам, поэтому просто включите это экспериментальное предупреждение, как и любые другие экспериментальные предупреждения:

no warnings qw(experimental::vlb);

Примечание. Убедитесь, что приведенная выше строка размещена после строки use warnings;, если она присутствует, иначе она не будет иметь длительного эффекта, поскольку будет переопределена строкой use warnings;.

person Wiktor Stribiżew    schedule 31.10.2020
comment
Предупреждение заключается в том, что в качестве экспериментальной функции могут быть ошибки, она может быть изменена без предварительного уведомления и может быть удалена без предварительного уведомления. - person ikegami; 31.10.2020

Perl не волнует, предоставляется ли код через -e или через файл. Код ведет себя одинаково в обеих ситуациях. Причина сбоя не в том, что вы использовали код, который вы разместили в файле, а не в командной строке. Есть еще одна разница, которую вы не определили, вызывающая разницу в поведении.


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

Вы можете исключить использование экспериментального ретроспективного просмотра переменной длины, используя вместо этого следующее:

s/(?:href|src).{0,40}(*SKIP)(*FAIL)|jpg//g

(*FAIL) заставляет шаблон не совпадать и, таким образом, запускает поиск с возвратом. Но (*SKIP) сделал так, что он начнет совпадать с позиции после строки, совпадающей с (?:href|src).{0,40}, в будущих попытках.

person ikegami    schedule 01.11.2020