#regex #perl
#регулярное выражение #perl
Вопрос:
В моем скрипте есть регулярное выражение, которое я написал много лет назад.
Я знаю, что делает это регулярное выражение (ищет проценты выше 80%), но я не помню его значения / принципов. Я вижу, что используется троичный оператор, а также последнее совпадение закрытых скобок, но чего я, например, не знаю, так это значения ??
:
qr/^(d )%$(??{$^N>= 80 ? '':'^'})/
Кто-нибудь может объяснить это регулярное выражение для меня?
Комментарии:
1. perldoc.pl/perlre #(??{-код-})
2. и это довольно сложная функция, кстати. Почему бы и нет
if ( (/^([0-9] )s*%/)[0] > 80 )
…3. @zdim хороший. Не могу вспомнить, почему я использовал встроенный код. Я также попробую ваше решение.
Ответ №1:
Прежде чем я отвечу, я хотел бы отметить, что использование встроенной формы кода perl (??...)
может быть чревато ошибками, если вы не до конца понимаете его последствия. Я пишу perl regexen более двадцати лет, и моя естественная тенденция — всегда кодировать «вариант использования», подобный этому, в качестве фильтра для результата регулярного выражения, а не встраивать код perl непосредственно в регулярное выражение. Вы были предупреждены.
Хорошо, давайте разберем это регулярное выражение отдельно:
^ # start of text
( # begin capture group
d # one or more digits 0-9
) # end of capture group
% # literal percent sign character
$ # end of text
(??{ # start embedded perl code
$^N >= 80 # if last closed match group($^N) is greater than or equal to 80
? '' # then return empty pattern ('')
: '^' # else return start of text (^) pattern
}) # end embedded perl code
где $^N
ссылается на значение самой последней закрытой пары совпадений, и (??{ ... })
предложение нулевой ширины выполнит код perl, который он переносит, преобразуя возвращаемое значение в новое регулярное выражение, которое будет добавлено к исходному шаблону.
Итак, в этом примере мы сопоставляем одну или несколько цифр, за которыми сразу следует символ знака процента. Затем, если захваченное значение больше или равно 80, вычислите пустой шаблон по тексту (эффективно позволяя общему шаблону совпадать, возвращая захваченное значение), или, если нет, вычислите шаблон ^
(начало текста), который не может совпадать в конце строки, эффективно возвращаяничего.
(Обратите внимание, что, добавив модификатор / x к вашему регулярному выражению Perl, вы можете вставлять комментарии непосредственно в шаблон, который также будет игнорировать встроенные пробелы. Я обнаружил, что это отличный способ документировать сложные регулярные выражения.)
Комментарии:
1. О, и следует отметить, что группа захвата будет соответствовать значениям, превышающим 100%, что, вероятно, не то, что задумано. Измените группу захвата на
100|d{1,2}
соответствие значениям от 0 до 100.2. очень хороший момент. Однако в этом случае значение не может превышать 100%, поскольку мы говорим об ИСПОЛЬЗОВАНИИ ДИСКА
3. Конечно, но регулярное выражение, которое вы хотите понять , допускает значения больше 100.
Ответ №2:
$(??{code})
выполняет code
, а затем заменяет результат в регулярное выражение. В этом случае $^N
заменяется тем, что соответствует самой последней группе захвата (d )
. Затем регулярное выражение с этой заменой сопоставляется снова.
Итак, если строка начинается с числа, за которым следует %
, ^(d )%
соответствует этому. Затем оно выполняется $^N >= 80 ? '' : '^'
, $^N
заменяясь на число. Если число не меньше 80
, регулярное выражение становится ^(d )%
, и все совпадение завершается успешно. Но если число меньше 80
, оно становится ^(d )%^
. Поскольку второе ^
не может совпадать в середине строки, регулярное выражение больше не совпадает.
Итак, это регулярное выражение соответствует строкам, которые начинаются с процента не менее 80.
Комментарии:
1. фантастика, большое вам спасибо. Если вы когда-нибудь напишете книгу о программировании, подпишите меня. Я сделаю предварительный заказ 🙂