perlre
СОДЕРЖАНИЕ
- НАЗВАНИЕ
- ОПИСАНИЕ
- Основы
- Модификаторы
- Регулярные выражения
- Цитирование метасимволов
- Расширенные шаблоны
- Обратное отслеживание
- Выполнения скриптов
- Специальные управляющие глаголы обратного отслеживания
- Предупреждение о \1 вместо $1
- Повторные шаблоны, соответствующие подстроке длиной ноль
- Комбинирование частей регулярных выражений
- Создание собственных движков регулярных выражений
- Частота выполнения встроенного кода
- Поддержка PCRE/Python
- ОШИБКИ
- СМОТРИТЕ ТАКЖЕ
НАЗВАНИЕ
perlre - Регулярные выражения Perl
ОПИСАНИЕ
Эта страница описывает синтаксис регулярных выражений в Perl.
Если вы раньше не использовали регулярные выражения, в perlretut доступен вводный учебник. Если вы знаете о них немного, в perlrequick доступен краткий вводный курс.
За исключением раздела "Основы", на этой странице предполагается, что вы знакомы с основами регулярных выражений, такими как что такое "шаблон", как он выглядит и как он используется в основном. Для справки по их использованию, а также различных примерах того же, см. обсуждения m//, s///, qr// и "??" в "Операторы цитирования регулярных выражений" в perlop.
Новое в версии 5.22, use re 'strict' применяет более строгие правила при компиляции шаблонов регулярных выражений. Он может обнаружить то, что, хотя и законно, может не быть тем, что вы имели в виду.
Основы
Регулярные выражения — это строки со специфическим синтаксисом и значением, описанным в этом документе и дополнительных документах, на которые он ссылается. Эти строки называются "шаблонами". Шаблоны используются для определения, содержит ли другая строка, называемая "целевой", характеристики, указанные в шаблоне. Мы называем это "сопоставлением" целевой строки с шаблоном. Обычно сопоставление выполняется путем использования целевой строки в качестве первого операнда и шаблона — во втором операнде одного из двух бинарных операторов =~ и !~, перечисленных в "Операторы связывания" в perlop; и шаблон будет преобразован из обычной строки одним из операторов в "Операторы цитирования регулярных выражений" в perlop, например:
$foo =~ m/abc/ Это истинно тогда и только тогда, когда строка в переменной $foo содержит последовательность символов "a", "b" и затем "c". (Оператор сопоставления =~ m, описан в "m/PATTERN/msixpodualngc" в perlop.)
Шаблоны, которые не хранятся в переменной, должны быть ограничены с обоих концов символами-разделителями. Часто, как в примере выше, это слэши, и типичный способ написания шаблона в документации — с использованием этих слэшей. В большинстве случаев разделитель — один и тот же символ, но есть несколько случаев, где символ кажется зеркальным отображением, где открытая версия — начальный разделитель, а закрытая — конечный разделитель, как
$foo =~ m<abc> В большинстве случаев шаблон оценивается в контексте двойных кавычек, но есть возможность выбрать разделители для принудительного использования одинарных кавычек, например
$foo =~ m'abc' Если шаблон содержит свой разделитель внутри него, этот разделитель необходимо экранировать. Предварительное добавление обратного слэша (например, "/foo\/bar/") служит этой цели.
Любой одиночный символ в шаблоне соответствует этому же символу в целевой строке, если этот символ не является метасимволом со специальным значением, описанным в этом документе. Последовательность неметасимволов соответствует той же последовательности в целевой строке, как мы видели выше в m/abc/.
Только несколько символов (все из них — ASCII-знаки препинания) являются метасимволами. Наиболее часто используемый — точка ".", которая обычно соответствует почти любому символу (включая саму точку).
Вы можете заставить символы, которые обычно работают как метасимволы, интерпретироваться буквально, предваряя их обратным слэшем "\", точно так же, как разделитель шаблона должен быть экранирован, если он также встречается в шаблоне. Таким образом, "\." соответствует только буквальной точке, "." вместо его обычного значения. Это означает, что обратный слэш также является метасимволом, поэтому "\\" соответствует одному "\". А последовательность, содержащая экранированный метасимвол, соответствует той же последовательности (но без экранирования) в целевой строке. Итак, шаблон /blur\\fl/ соответствовал бы любой целевой строке, содержащей последовательность "blur\fl".
Метасимвол "|" используется для сопоставления одного или другого. Таким образом
$foo =~ m/this|that/ ИСТИННО тогда и только тогда, когда $foo содержит либо последовательность "this", либо последовательность "that". Как и все метасимволы, предваряя "|" обратным слэшем, вы получаете сопоставление с обычным символом препинания; в данном случае — с вертикальной чертой.
$foo =~ m/this\|that/ ИСТИННО тогда и только тогда, когда $foo содержит последовательность "this|that".
Вы не ограничены только одним "|".
$foo =~ m/fee|fie|foe|fum/ ИСТИННО тогда и только тогда, когда $foo содержит любую из этих 4 последовательностей из детской истории "Джек и бобовый стебель".
Как вы можете видеть, метасимвол "|" связывается слабее, чем последовательность обычных символов. Мы можем переопределить это, используя метасимволы группирования, круглые скобки "(" и ")".
$foo =~ m/th(is|at) thing/ ИСТИННО тогда и только тогда, когда $foo содержит либо последовательность "this thing", либо последовательность "that thing". Части строки, соответствующие частям шаблона в скобках, обычно доступны отдельно для последующего использования в шаблоне, замене или программе. Это называется "захватом", и это может усложняться. См. "Группы захвата".
Первый альтернативный вариант включает в себя все от последнего разделителя шаблона ("(", "(?:" (описано позже), и т.д. или начала шаблона) до первого "|", а последний альтернативный вариант содержит все от последнего "|" до следующего закрывающего разделителя шаблона. Вот почему принято заключать альтернативы в скобки: для минимизации путаницы с их началом и концом.
Альтернативные варианты проверяются слева направо, поэтому первый найденный альтернативный вариант, для которого соответствует все выражение, — это тот, который выбирается. Это означает, что альтернативные варианты не обязательно жадные. Например: при сопоставлении foo|foot с "barefoot", только часть "foo" будет соответствовать, так как это первый альтернативный вариант, который проверяется и успешно сопоставляется с целевой строкой. (Это может показаться неважным, но это важно, когда вы захватываете сопоставленный текст с помощью скобок.)
Помимо удаления специального значения метасимвола, предваренный обратным слэшем символ изменяет некоторые буквенные и цифровые символы от соответствия только себе, а вместо этого получает специальное значение. Это называются "экранированными последовательностями", и все они описаны в perlrebackslash. Последовательность обратного слэша (буквы или цифры), которая в настоящее время не имеет специального значения для Perl, вызовет предупреждение, если включены предупреждения, поскольку они зарезервированы для потенциального будущего использования.
Одна из таких последовательностей — \b, которая соответствует границе некоторого рода. \b{wb} и несколько других дают специализированные типы границ. (Все они подробно описаны, начиная с "\b{}, \b, \B{}, \B" в perlrebackslash.) Обратите внимание, что они не соответствуют символам, а нулевым пространствам между символами. Они являются примером утверждения нулевой ширины. Рассмотрим снова,
$foo =~ m/fee|fie|foe|fum/ Это оценивается как ИСТИНА, если помимо этих 4 слов, в $foo есть какие-либо последовательности "feed", "field", "Defoe", "fume" и многие другие. С помощью продуманного использования \b (или, что лучше (потому что оно разработано для обработки естественного языка), \b{wb}), мы можем убедиться, что сопоставляются только слова великана:
$foo =~ m/\b(fee|fie|foe|fum)\b/
$foo =~ m/\b{wb}(fee|fie|foe|fum)\b{wb}/ В последнем примере показано, что символы "{" и "}" являются метасимволами.
Другое применение для последовательностей escape — указать символы, которые нельзя (или которые вы предпочитаете не) записывать буквально. Подробное описание приведено в "Character Escapes" в perlrebackslash, но в следующих трёх абзацах кратко описаны некоторые из них.
Различные управляющие символы могут быть записаны в стиле языка C: "\n" соответствует новой строке, "\t" — табуляции, "\r" — возврату каретки, "\f" — переводу страницы, и т.д.
В более общем случае, \nnn, где nnn — строка из трёх восьмеричных цифр, соответствует символу, код которого равен nnn. Вы легко можете столкнуться с проблемами, если у вас не ровно три цифры. Поэтому всегда используйте три цифры, или, начиная с Perl 5.14, вы можете использовать \o{...} для указания любого числа восьмеричных цифр.
Аналогично, \xnn, где nn — шестнадцатеричные цифры, соответствует символу, порядковый номер которого равен nn. Снова, неиспользование ровно двух цифр — путь к катастрофе, но вы можете использовать \x{...} для указания любого числа шестнадцатеричных цифр.
Помимо того, что "." является метасимволом, он также является примером «класса символов», который может соответствовать любому одиночному символу из заданного набора. В его случае, набор включает практически все возможные символы. Perl предопределяет несколько классов символов помимо "."; отдельная справочная страница посвящена именно им, perlrecharclass.
Вы можете определить свои собственные пользовательские классы символов, поместив в своё выражение в соответствующем месте список всех символов, которые вы хотите включить в набор. Для этого заключите список в [] квадратные скобки. Эти классы называются «классами символов в квадратных скобках», когда мы точны, но часто слово «в квадратных скобках» опускается. (Обычно это не приводит к путанице.) Это означает, что "[" символ — ещё один метасимвол. Он сам по себе ничего не сопоставляет; он используется только для того, чтобы указать Perl, что то, что следует за ним, — это класс символов в квадратных скобках. Если вы хотите сопоставить буквальный открывающий квадратную скобку, вам нужно экранировать её, как "\[". Соответствующий "]" также является метасимволом; он опять же сам по себе ничего не сопоставляет, но лишь указывает Perl на конец вашего пользовательского класса. Это пример «иногда метасимвола». Он не является метасимволом, если нет соответствующего "[", и соответствует своему буквальному значению:
print "]" =~ /]/; # prints 1 Список символов внутри класса символов задаёт набор символов, сопоставляемых классом. "[abc]" соответствует одному символу "a", "b" или "c". Но если первый символ после "[" — "^", класс вместо этого сопоставляет любой символ, не входящий в список. Внутри списка "-" символ указывает диапазон символов, так что a-z представляет все символы от "a" до "z", включительно. Если вы хотите, чтобы "-" или "]" сами были членами класса, поместите их в начало списка (возможно, после "^") или экранируйте их обратной косой чертой. "-" также интерпретируется буквально, когда он находится в конце списка, непосредственно перед закрывающей "]". (Следующие все определяют один и тот же класс из трёх символов: [-az], [az-], и [a\-z]. Все они отличаются от [a-z], который определяет класс, содержащий двадцать шесть символов, даже на наборах символов на базе EBCDIC.)
Существует множество других деталей о классах символов в квадратных скобках; полные детали находятся в "Bracketed Character Classes" в perlrecharclass.
Метасимволы
"The Basics" ввело некоторые метасимволы. Этот раздел содержит все из них. Большинство из них имеют тот же смысл, что и в команде egrep.
Только "\" всегда является метасимволом. Другие являются метасимволами только иногда. В следующих таблицах перечислены все из них, подытожены их использование и указаны контексты, в которых они являются метасимволами. Вне этих контекстов или если они префиксны "\", они соответствуют соответствующему знаку препинания. В некоторых случаях их значение варьируется в зависимости от различных модификаторов шаблонов, которые изменяют стандартное поведение. Смотрите "Модификаторы".
PURPOSE WHERE
\ Escape the next character Always, except when
escaped by another \
^ Match the beginning of the string Not in []
(or line, if /m is used)
^ Complement the [] class At the beginning of []
. Match any single character except newline Not in []
(under /s, includes newline)
$ Match the end of the string Not in [], but can
(or before newline at the end of the mean interpolate a
string; or before any newline if /m is scalar
used)
| Alternation Not in []
() Grouping Not in []
[ Start Bracketed Character class Not in []
] End Bracketed Character class Only in [], and
not first
* Matches the preceding element 0 or more Not in []
times
+ Matches the preceding element 1 or more Not in []
times
? Matches the preceding element 0 or 1 Not in []
times
{ Starts a sequence that gives number(s) Not in []
of times the preceding element can be
matched
{ when following certain escape sequences
starts a modifier to the meaning of the
sequence
} End sequence started by {
- Indicates a range Only in [] interior
# Beginning of comment, extends to line end Only with /x modifier Обратите внимание, что большинство метасимволов теряют свой особый смысл при появлении в классе символов в квадратных скобках, за исключением "^", который имеет другое значение, когда находится в начале такого класса. А "-" и "]" являются метасимволами только в ограниченных позициях внутри классов символов в квадратных скобках; в то время как "}" является метасимволом только при закрытии специальной конструкции, начатой "{".
В контексте двойных кавычек, как обычно, нужно быть осторожным с "$" и неметасимволом "@". Они могут интерполировать переменные, что может или не может соответствовать вашим намерениям.
Эти правила были разработаны для краткости выражений, а не для удобочитаемости и поддерживаемости. Модификаторы шаблонов "/x и /xx" позволяют вставлять пробелы для улучшения удобочитаемости. А использование re 'strict' добавляет дополнительную проверку, чтобы поймать некоторые опечатки, которые могут незаметно скомпилироваться в что-то нежелательное.
По умолчанию символ "^" гарантированно соответствует только началу строки, символ "$" только концу (или перед символом новой строки в конце), и Perl выполняет определённые оптимизации с предположением, что строка содержит только одну строку. Встроенные символы новой строки не будут сопоставлены с "^" или "$". Однако, возможно, вы захотите обращаться со строкой как с буфером с несколькими строками, так что "^" будет соответствовать после любой новой строки в строке (за исключением случая, когда новая строка — последний символ в строке), а "$" будет соответствовать перед любой новой строкой. За счёт небольшого увеличения нагрузки вы можете сделать это, используя модификатор "/m" для оператора поиска по шаблону. (Старые программы делали это, устанавливая $*, но этот параметр был удален в perl 5.10.)
Для упрощения замещений в нескольких строках символ "." никогда не соответствует новой строке, если вы не используете модификатор /s, который фактически заставляет Perl представлять строку как одну строку — даже если она не является таковой.
Модификаторы
Обзор
Стандартное поведение поиска по шаблону может быть изменено с помощью различных модификаторов. Модификаторы, относящиеся к интерпретации шаблона, перечислены непосредственно ниже. Модификаторы, которые изменяют способ использования шаблона Perl, подробно описаны в "Regexp Quote-Like Operators" в perlop и "Gory details of parsing quoted constructs" в perlop.
-
m -
Обрабатывайте строку, с которой производится сопоставление, как многострочную. То есть, изменяйте
"^"и"$"с сопоставления начала первой строки и конца последней строки на сопоставление начала и конца каждой строки в строке. -
s -
Обрабатывайте строку как однострочную. То есть, изменяйте
"."на сопоставление любого символа, даже новой строки, с которым обычно не производится сопоставление.Используемые вместе, как
/ms, они позволяют"."сопоставлять любой символ, сохраняя при этом возможность"^"и"$"сопоставлять, соответственно, сразу после и сразу перед новой строкой в строке. -
i -
Производить сопоставление шаблона без учета регистра. Например, "A" будет соответствовать "a" при
/i.Если правила сопоставления по локали активны, карта регистров берется из текущей локали для кодовых точек меньше 255 и из правил Юникода для больших кодовых точек. Однако, сопоставления, которые пересекают границу правил Юникода/не Юникода (ords 255/256), не будут успешными, если локаль не является UTF-8. См. perllocale.
Существует ряд символов Юникода, которые соответствуют последовательности нескольких символов при
/i. Например,LATIN SMALL LIGATURE FIдолжно соответствовать последовательностиfi."\N{LATIN SMALL LIGATURE FI}" =~ /fi/i; # Matches "\N{LATIN SMALL LIGATURE FI}" =~ /[fi][fi]/i; # Doesn't match! "\N{LATIN SMALL LIGATURE FI}" =~ /fi*/i; # Doesn't match! # The below doesn't match, and it isn't clear what $1 and $2 would # be even if it did!! "\N{LATIN SMALL LIGATURE FI}" =~ /(f)(i)/i; # Doesn't match!Perl в настоящее время не может выполнить это, когда несколько символов находятся в шаблоне и разделены группами, или когда один или несколько из них квантифицированы. Таким образом
"\N{LATIN SMALL LIGATURE FI}" =~ /fi/i; # Matches "\N{LATIN SMALL LIGATURE FI}" =~ /[fi][fi]/i; # Doesn't match! "\N{LATIN SMALL LIGATURE FI}" =~ /fi*/i; # Doesn't match! # The below doesn't match, and it isn't clear what $1 and $2 would # be even if it did!! "\N{LATIN SMALL LIGATURE FI}" =~ /(f)(i)/i; # Doesn't match!Perl не сопоставляет несколько символов в скобочном классе символов, если символ, которому они соответствуют, не указан явно, и не сопоставляет их вообще, если скобочный класс инвертирован, что в противном случае может быть очень запутанно. См. "Bracketed Character Classes" в perlrecharclass и "Negation" в perlrecharclass.
-
xиxx -
Улучшите читаемость шаблона, разрешив пробелы и комментарии. Подробности в "/x и /xx"
-
p -
Сохраните сопоставленную строку таким образом, что
${^PREMATCH},${^MATCH}, и${^POSTMATCH}будут доступны для использования после сопоставления.В Perl 5.20 и выше это игнорируется. Из-за новой механизма копирования при записи
${^PREMATCH},${^MATCH}, и${^POSTMATCH}будут доступны после сопоставления независимо от модификатора. -
a,d,l, иu -
Эти модификаторы, все новые в 5.14, влияют на используемые правила набора символов (Юникод и т. д.), как описано ниже в "Модификаторы набора символов".
-
n -
Предотвратите захват метасимволов группирования
(). Этот модификатор, новый в 5.22, остановит$1,$2, и т. д. от заполнения."hello" =~ /(hi|hello)/; # $1 is "hello" "hello" =~ /(hi|hello)/n; # $1 is undefЭто эквивалентно добавлению
?:в начале каждой захватывающей группы:"hello" =~ /(?:hi|hello)/; # $1 is undef/nможет быть отменено на основе каждой группы. Кроме того, все еще можно использовать именованные захваты."hello" =~ /(?-n:(hi|hello))/n; # $1 is "hello" "hello" =~ /(?<greet>hi|hello)/n; # $1 is "hello", $+{greet} is # "hello" - Дополнительные модификаторы
-
Есть ряд флагов, которые можно найти в конце конструкций регулярных выражений, которые не являются общими флагами регулярных выражений, но применяются к выполняемой операции, например, к сопоставлению или подстановке (
m//илиs///соответственно).Флаги, описанные подробнее в "Использование регулярных выражений в Perl" в perlretut:
c - keep the current position during repeated matching g - globally match the pattern repeatedly in the stringМодификаторы, относящиеся к подстановке, описанные в "s/PATTERN/REPLACEMENT/msixpodualngcer" в perlop:
e - evaluate the right-hand side as an expression ee - evaluate the right side as a string then eval the result o - pretend to optimize your code, but actually introduce bugs r - perform non-destructive substitution and return the new value
Модификаторы регулярных выражений обычно пишутся в документации, например, "модификатор /x", даже если разделитель в данном случае не является косой чертой. Модификаторы /imnsxadlup также могут быть встроены в само регулярное выражение с использованием конструкции (?...), см. "Расширенные шаблоны" ниже.
Подробности о некоторых модификаторах
Некоторые из модификаторов требуют более подробного объяснения, чем указано в "Обзор" выше.
/x и /xx
Один /x сообщает парсеру регулярных выражений игнорировать большинство пробелов, которые не обработаны обратным слешем или не находятся в скобочном классе символов. Вы можете использовать это, чтобы разбить ваше регулярное выражение на более удобочитаемые части. Кроме того, символ "#" обрабатывается как метасимвол, вводящий комментарий, который продолжается до закрывающего разделителя шаблона или до конца текущей строки, если шаблон переходит на следующую строку. Следовательно, это очень похоже на обычный Perl-комментарий. (Вы можете включить закрывающий разделитель в комментарий, только если вы поместите перед ним обратный слэш, поэтому будьте осторожны!)
Использование /x означает, что если вы хотите реальные пробелы или "#" символы в шаблоне (вне скобочного класса символов, который не затрагивается /x), то вам придется либо экранировать их (используя обратные слэши или \Q...\E ) или закодировать их с использованием восьмеричных, шестнадцатеричных или \N{} эскейпов. Бесполезно пытаться продолжить комментарий на следующую строку, экранируя \n обратным слэшем или \Q.
Вы можете использовать "(?#text)", чтобы создать комментарий, который заканчивается раньше, чем конец текущей строки, но text также не может содержать закрывающий разделитель, если он не экранирован обратным слешем.
Частая ошибка заключается в том, что вы забываете, что "#" символы начинают комментарий при /x и не соответствуют буквально. Просто имейте это в виду, когда пытаетесь понять, почему определенный /x шаблон не работает так, как ожидалось.
Начиная с Perl v5.26, если модификатор имеет второй "x" внутри него, он делает все, что делает одиночный /x, но дополнительно необработанные пробелы и табуляции в скобочных классах символов также обычно игнорируются и, следовательно, могут быть добавлены, чтобы сделать классы более удобочитаемыми.
/ [d-e g-i 3-7]/xx
/[ ! @ " # $ % ^ & * () = ? <> ' ]/xx возможно, будет легче понять, чем сжатые эквиваленты
/[d-eg-i3-7]/
/[!@"#$%^&*()=?<>']/ В совокупности эти функции значительно повышают удобочитаемость регулярных выражений Perl. Вот пример:
# Delete (most) C comments.
$program =~ s {
/\* # Match the opening delimiter.
.*? # Match a minimal number of characters.
\*/ # Match the closing delimiter.
} []gsx; Обратите внимание, что все внутри \Q...\E остается без изменений под влиянием /x. Обратите внимание, что /x не влияет на интерпретацию пробелов внутри одного многосимвольного конструкта. Например, в \x{...}, независимо от модификатора /x, пробелов быть не может. То же самое для квантификатора, такого как {3} или {5,}. Аналогично, (?:...) не может иметь пробела между "(", "?" и ":". Внутри любых разделителей для такого конструкта разрешенные пробелы не затрагиваются /x, и зависят от конструкта. Например, \x{...} не может иметь пробелов, так как шестнадцатеричные числа не имеют пробелов. Но свойства Юникода могут иметь пробелы, поэтому в \p{...} могут быть пробелы, которые следуют правилам Юникода, см. "Свойства, доступные через \p{} и \P{}" в perluniprops.
Набор символов, которые считаются пробелами, — это те, что Юникод называет "Пробелами шаблона", а именно:
U+0009 CHARACTER TABULATION
U+000A LINE FEED
U+000B LINE TABULATION
U+000C FORM FEED
U+000D CARRIAGE RETURN
U+0020 SPACE
U+0085 NEXT LINE
U+200E LEFT-TO-RIGHT MARK
U+200F RIGHT-TO-LEFT MARK
U+2028 LINE SEPARATOR
U+2029 PARAGRAPH SEPARATOR Модификаторы набора символов
/d, /u, /a, и /l, доступные начиная с версии 5.14, называются модификаторами набора символов; они влияют на используемые правила набора символов для регулярного выражения.
Модификаторы /d, /u, и /l вряд ли будут вам полезны, поэтому вам не нужно сильно беспокоиться о них. Они существуют для внутреннего использования Perl, чтобы сложные структуры данных регулярных выражений могли быть автоматически сериализованы и впоследствии точно восстановлены, включая все их нюансы. Но, так как Perl не умеет хранить секреты, и могут быть редкие случаи, когда они полезны, они описаны здесь.
Модификатор /a может быть полезным. Его цель состоит в том, чтобы код, который в основном работает с данными ASCII, не должен был беспокоиться о Юникоде.
Кратко, /l устанавливает набор символов в соответствии с текущей локалью во время выполнения сопоставления шаблона.
/u устанавливает набор символов в Юникод.
/a также устанавливает набор символов в Юникод, НО добавляет несколько ограничений для обеспечения безопасности сопоставлений ASCII.
/d — это старое, проблемное поведение набора символов по умолчанию до версии 5.14. Его единственное назначение — принудительно использовать старое поведение.
В любой момент времени активен ровно один из этих модификаторов. Их существование позволяет Perl сохранять исходное поведение скомпилированного регулярного выражения, независимо от правил, действующих при его фактическом выполнении. И если оно интерполируется в большее регулярное выражение, оригинальные правила продолжают к нему применяться, и только к нему.
Модификаторы /l и /u автоматически выбираются для регулярных выражений, скомпилированных в рамках различных прагм, и мы рекомендуем, чтобы в общем случае вы использовали эти прагмы вместо явного указания этих модификаторов. Во-первых, модификаторы влияют только на сопоставление шаблонов и не распространяются даже на любые подстановки, тогда как использование прагм дает согласованные результаты для всех соответствующих операций в рамках их области действия. Например,
s/foo/\Ubar/il сопоставит "foo" с использованием правил локали для сопоставления без учета регистра, но /l не влияет на то, как работает \U. Скорее всего, вы хотите, чтобы оба они использовали правила локали. Для этого вместо этого скомпилируйте регулярное выражение в рамках use locale. Это неявным образом добавляет /l и применяет правила локали к \U. Урок заключается в use locale, а не в /l явно.
Аналогичным образом, было бы лучше использовать use feature 'unicode_strings' вместо,
s/foo/\Lbar/iu чтобы получить правила Unicode, так как \L в первом (но не обязательно во втором) случае также будут использовать правила Unicode.
Более подробная информация о каждом из модификаторов приведена ниже. Вероятнее всего, вам не нужно знать эти детали для /l, /u, и /d, и вы можете перейти к /a.
/l
означает использование правил текущего языка (см. perllocale) при сопоставлении с образцом. Например, \w будет соответствовать символам «слова» этого языка, а "/i" сопоставление без учёта регистра будет соответствовать правилам преобразования регистра, определённым языком. Используемый язык будет тем, который активен во время выполнения сопоставления с образцом. Он может отличаться от языка, используемого во время компиляции, и может изменяться от одного сопоставления к другому, если была вызвана функция setlocale().
До версии v5.20 Perl не поддерживал многобайтовые языки. Начиная с этой версии, поддерживаются языки UTF-8. Другие многобайтовые языки вряд ли будут поддерживаться. Однако во всех языках могут присутствовать кодовые точки выше 255, и они всегда будут обрабатываться как Unicode, независимо от используемого языка.
Согласно правилам Unicode, существует несколько сопоставлений без учёта регистра, которые пересекают границу 255/256. За исключением языков UTF-8 в Perl v5.20 и более поздних версий, они запрещены в /l. Например, 0xFF (на платформах ASCII) не соответствует символу в 0x178 без учёта регистра, LATIN CAPITAL LETTER Y WITH DIAERESIS, потому что 0xFF может не быть LATIN SMALL LETTER Y WITH DIAERESIS в текущем языке, и Perl не знает, существует ли этот символ в языке, и какой кодовой точкой он представлен.
В языке UTF-8 в v5.20 и более поздних версиях единственное заметное различие между языком и неязыком в регулярных выражениях должно заключаться в заражении (см. perlsec).
Этот модификатор может быть задан по умолчанию use locale, но см. "Какой модификатор набора символов используется?".
/u
означает использование правил Unicode при сопоставлении с образцом. На платформах ASCII это означает, что кодовые точки между 128 и 255 получают свои значения Latin-1 (ISO-8859-1) (которые совпадают со значениями Unicode). (В противном случае Perl считает их значения неопределёнными.) Таким образом, при этом модификаторе платформа ASCII фактически становится платформой Unicode; следовательно, например, \w будет соответствовать любому из более чем 100 000 символов «слова» в Unicode.
В отличие от большинства языков, которые специфичны для пары язык-страна, Unicode классифицирует все символы, которые являются буквами где-то в мире, как \w. Например, ваш язык может не считать, что LATIN SMALL LETTER ETH является буквой (если вы не говорите по-исландски), но Unicode считает. Аналогично, все символы, являющиеся десятичными цифрами где-то в мире, будут соответствовать \d; это сотни, а не 10 возможных совпадений. И некоторые из этих цифр похожи на некоторые из 10 ASCII цифр, но означают другое число, поэтому человек может легко подумать, что число имеет другое значение, чем оно есть на самом деле. Например, BENGALI DIGIT FOUR (U+09EA) очень похож на ASCII DIGIT EIGHT (U+0038). И, \d+, может соответствовать строкам цифр, которые являются смесью из разных систем письма, создавая проблему безопасности. "num()" в Unicode::UCD можно использовать для решения этой проблемы. Или модификатор /a можно использовать для принудительного соответствия \d только ASCII цифрам от 0 до 9.
Кроме того, при этом модификаторе сопоставление без учёта регистра работает со всем набором символов Unicode. Например, KELVIN SIGN соответствует буквам «k» и «K»; а LATIN SMALL LIGATURE FF соответствует последовательности «ff», что, если вы к этому не готовы, может заставить это выглядеть как шестнадцатеричная константа, представляя ещё одну потенциальную проблему безопасности. Подробное обсуждение проблем безопасности Unicode см. в http://unicode.org/reports/tr36.
Этот модификатор может быть установлен по умолчанию use feature 'unicode_strings, use locale ':not_characters', или use 5.012 (или выше), но см. "Какой модификатор набора символов используется?".
/d
Этот модификатор означает использование «стандартных» правил платформы, за исключением случаев, когда вместо этого необходимо использовать правила Unicode, а именно:
-
целевая строка закодирована в UTF-8;
-
образец закодирован в UTF-8;
-
образец явно упоминает кодовую точку, которая превышает 255 (скажем,
\x{100}); -
образец использует имя Unicode (
\N{...}); -
образец использует свойство Unicode (
\p{...}или\P{...}); -
образец использует разрыв Unicode (
\b{...}или\B{...}); -
образец использует "
(?[ ])" -
образец использует
(*script_run: ...)
Ещё одним мнемоническим обозначением для этого модификатора является «Зависит», так как фактически используемые правила зависят от различных факторов, и в результате вы можете получить неожиданные результаты. См. "Ошибка Unicode" в perlunicode. Ошибка Unicode стала довольно печально известной, что привело к ещё одному (печатному) названию для этого модификатора — «Ненадёжный».
Если образец или строка не закодированы в UTF-8, только символы ASCII могут быть сопоставлены положительно.
Вот несколько примеров того, как это работает на платформе ASCII:
$str = "\xDF"; # $str is not in UTF-8 format.
$str =~ /^\w/; # No match, as $str isn't in UTF-8 format.
$str .= "\x{0e0b}"; # Now $str is in UTF-8 format.
$str =~ /^\w/; # Match! $str is now in UTF-8 format.
chop $str;
$str =~ /^\w/; # Still a match! $str remains in UTF-8 format. Этот модификатор автоматически выбирается по умолчанию, когда ни один из других не выбран, поэтому ещё одно название для него — «По умолчанию».
Из-за неожиданного поведения, связанного с этим модификатором, вы, вероятно, должны использовать его только явно для сохранения странных обратных совместимостей.
/a (и /aa)
Этот модификатор означает ограничение ASCII (или безопасный ASCII). Этот модификатор можно удваивать для увеличения его эффекта.
Когда он появляется один раз, он заставляет последовательности \d, \s, \w, и классы символов Posix соответствовать только в диапазоне ASCII. Таким образом, они возвращаются к своим значениям до версии 5.6, до Unicode. В /a, \d всегда означает точно цифры "0" до "9"; \s означает пять символов [ \f\n\r\t], а начиная с Perl v5.18, вертикальную табуляцию; \w означает 63 символа [A-Za-z0-9_]; и аналогично, все классы Posix, такие как [[:print:]] соответствуют только соответствующим символам диапазона ASCII.
Этот модификатор полезен для людей, которые случайно используют Unicode и не хотят быть обременёнными его сложностями и проблемами безопасности.
С помощью /a, можно написать \d с уверенностью, что он будет соответствовать только символам ASCII, а в случае необходимости сопоставления с символами вне ASCII, можно использовать \p{Digit} (или \p{Word} для \w). Существуют аналогичные конструкции \p{...}, которые могут соответствовать символам вне ASCII, как пробелам (см. "Пробелы" в perlrecharclass), так и классам Posix (см. "Классы символов POSIX" в perlrecharclass). Таким образом, этот модификатор не означает, что вы не можете использовать Unicode, он означает, что для получения сопоставления Unicode необходимо явно использовать конструкцию (\p{}, \P{}), которая сигнализирует о Unicode.
Как и ожидалось, этот модификатор заставляет, например, \D означать то же самое, что и [^0-9]; фактически, все символы, не являющиеся ASCII, соответствуют \D, \S, и \W. \b по-прежнему означает соответствие на границе между \w и \W, используя определения /a (аналогично для \B).
В противном случае /a ведет себя как модификатор /u, в том смысле, что сопоставление без учёта регистра использует правила Unicode; например, «k» будет соответствовать Unicode \N{KELVIN SIGN} при сопоставлении без учёта регистра, а кодовые точки в диапазоне Latin1, превышающие ASCII, будут иметь правила Unicode при сопоставлении без учёта регистра.
Чтобы запретить соответствие ASCII/не-ASCII (например, «k» с \N{KELVIN SIGN}), укажите модификатор "a" дважды, например, /aai или /aia. (Первый модификатор "a" ограничивает \d, и так далее, а второй добавляет ограничения /i.) Однако обратите внимание, что кодовые точки вне диапазона ASCII будут использовать правила Unicode для /i сопоставления, поэтому модификатор не ограничивает только ASCII; он просто запрещает смешивание ASCII и не-ASCII.
В резюме, этот модификатор предоставляет защиту для приложений, которые не хотят быть подвержены воздействию всех возможностей Unicode. Указание его дважды обеспечивает дополнительную защиту.
Этот модификатор может быть установлен по умолчанию use re '/a' или use re '/aa'. Если вы сделаете это, вам, возможно, потребуется использовать модификатор /u явно, если есть несколько регулярных выражений, где вы хотите полные правила Unicode (но даже здесь лучше, если всё будет под управлением функции "unicode_strings", вместе с use re '/aa'). Также см. "Какой модификатор набора символов используется?".
Какой модификатор набора символов используется?
Какой из этих модификаторов активен в любой момент времени в регулярном выражении зависит от достаточно сложной системы взаимодействий. Они были разработаны таким образом, что, как правило, вам не нужно беспокоиться об этом, но этот раздел содержит подробные сведения. Как объясняется ниже в "Расширенные образцы", можно явно указать модификаторы, которые применяются только к частям регулярного выражения. Внутренний модификатор всегда имеет приоритет над внешними, а модификатор, применяемый ко всему выражению, имеет приоритет над любыми значениями по умолчанию, описанными в остальной части данного раздела.
Предикат use re '/foo' может использоваться для установки модификаторов по умолчанию (включая эти) для регулярных выражений, скомпилированных в его области действия. Этот предикат имеет приоритет над другими предикатами, перечисленными ниже, которые также изменяют значения по умолчанию.
В противном случае, use locale устанавливает значение по умолчанию для модификатора в /l; а use feature 'unicode_strings, или use 5.012 (или выше) устанавливают значение по умолчанию в /u, если они не находятся в том же блоке кода, что и use locale или use bytes. (use locale ':not_characters' также устанавливает значение по умолчанию в /u, переопределяя любой обычный use locale. ) В отличие от вышеперечисленных механизмов, эти модификаторы влияют на операции, помимо сопоставления шаблонов регулярных выражений, и поэтому обеспечивают более согласованные результаты с другими операторами, включая использование \U, \l, и т.д. в операциях подстановки.
Если ни один из вышеперечисленных случаев не применим, для обеспечения обратной совместимости, модификатор /d используется по умолчанию. Поскольку это может привести к неожиданным результатам, рекомендуется указывать, какой набор правил следует использовать.
Поведение модификатора набора символов до Perl 5.14
До версии 5.14 явных модификаторов не было, но /l подразумевался для регулярных выражений, скомпилированных в пределах области действия use locale, а /d подразумевался в противном случае. Однако интерполяция регулярного выражения в большее регулярное выражение игнорирует исходную компиляцию в пользу того, что было установлено на момент второй компиляции. Возникало несколько несоответствий (ошибок) с модификатором /d, где правила Unicode использовались неуместно, и наоборот. \p{} не подразумевал правил Unicode, и то же самое относилось ко всем случаям \N{}, до версии 5.12.
Регулярные выражения
Квантификаторы
Квантификаторы используются, когда определенная часть шаблона должна соответствовать определенному числу (или числам) раз. Если квантификатора нет, то число соответствий равно ровно одному. Распознаются следующие стандартные квантификаторы:
* Match 0 or more times
+ Match 1 or more times
? Match 1 or 0 times
{n} Match exactly n times
{n,} Match at least n times
{n,m} Match at least n but not more than m times (Если неэкранированная фигурная скобка встречается в контексте, отличном от перечисленных выше квантификаторов, где она не является частью обратной последовательности, такой как \x{...}, она либо является синтаксической ошибкой, либо обрабатывается как обычный символ, обычно с предупреждением об устаревании. Чтобы экранировать её, можно поместить перед ней обратную косую черту ("\{") или заключить в квадратные скобки ("[{]"). Это изменение позволит в будущем расширять синтаксис (например, сделать необязательной нижнюю границу квантификатора) и улучшить проверку ошибок квантификаторов).
Квантификатор "*" эквивалентен {0,}, квантификатор "+" эквивалентен {1,}, а квантификатор "?" эквивалентен {0,1}. n и m ограничены неотрицательными целыми значениями, меньшими предопределённого предела, определённого при построении Perl. Обычно это 32766 на наиболее распространённых платформах. Фактический предел можно увидеть в сообщении об ошибке, сгенерированном кодом, таким как этот:
$_ **= $_ , / {$_} / for 2 .. 42; По умолчанию квантифицированный подшаблон является «жадным», то есть он будет соответствовать максимально возможному числу раз (при заданной начальной позиции), всё ещё позволяя остальной части шаблона соответствовать. Если вы хотите, чтобы он соответствовал минимальному возможному числу раз, добавьте после квантификатора "?". Обратите внимание, что значения не меняются, только «жадность»:
*? Match 0 or more times, not greedily
+? Match 1 or more times, not greedily
?? Match 0 or 1 time, not greedily
{n}? Match exactly n times, not greedily (redundant)
{n,}? Match at least n times, not greedily
{n,m}? Match at least n but not more than m times, not greedily Обычно, когда квантифицированный подшаблон не позволяет соответствовать остальной части общего шаблона, Perl выполняет возврат. Однако такое поведение иногда нежелательно. Поэтому Perl предоставляет также форму «поглощающего» квантификатора.
*+ Match 0 or more times and give nothing back
++ Match 1 or more times and give nothing back
?+ Match 0 or 1 time and give nothing back
{n}+ Match exactly n times and give nothing back (redundant)
{n,}+ Match at least n times and give nothing back
{n,m}+ Match at least n but not more than m times and give nothing back Например,
'aaaa' =~ /a++a/ никогда не будет соответствовать, так как a++ поглотит все "a" в строке и не оставит их для оставшейся части шаблона. Эта функция может быть чрезвычайно полезной для предоставления Perl подсказок о том, где не нужно выполнять возврат. Например, типичная проблема «сопоставления строки в двойных кавычках» наиболее эффективно выполняется, если записана как:
/"(?:[^"\\]++|\\.)*+"/ так как нам известно, что если заключительная кавычка не соответствует, возврат не поможет. Подробнее см. независимый подвыражение "(?>pattern)"; поглощающие квантификаторы — это просто синтаксический сахар для этого конструкта. Например, вышеприведенный пример можно также записать следующим образом:
/"(?>(?:(?>[^"\\]+)|\\.)*)"/ Обратите внимание, что модификатор поглощающего квантификатора не может быть объединен с модификатором нежадного квантификатора. Это потому, что это не имеет смысла. Рассмотрим следующую таблицу эквивалентности:
Illegal Legal
------------ ------
X??+ X{0}
X+?+ X{1}
X{min,max}?+ X{min} Последовательности экранирования
Поскольку шаблоны обрабатываются как строки в двойных кавычках, также работают следующие:
\t tab (HT, TAB)
\n newline (LF, NL)
\r return (CR)
\f form feed (FF)
\a alarm (bell) (BEL)
\e escape (think troff) (ESC)
\cK control char (example: VT)
\x{}, \x00 character whose ordinal is the given hexadecimal number
\N{name} named Unicode character or character sequence
\N{U+263D} Unicode character (example: FIRST QUARTER MOON)
\o{}, \000 character whose ordinal is the given octal number
\l lowercase next char (think vi)
\u uppercase next char (think vi)
\L lowercase until \E (think vi)
\U uppercase until \E (think vi)
\Q quote (disable) pattern metacharacters until \E
\E end either case modification or quoted section, think vi Подробности см. в "Quote and Quote-like Operators" in perlop.
Классы символов и другие специальные экранирования
Кроме того, Perl определяет следующее:
Sequence Note Description
[...] [1] Match a character according to the rules of the
bracketed character class defined by the "...".
Example: [a-z] matches "a" or "b" or "c" ... or "z"
[[:...:]] [2] Match a character according to the rules of the POSIX
character class "..." within the outer bracketed
character class. Example: [[:upper:]] matches any
uppercase character.
(?[...]) [8] Extended bracketed character class
\w [3] Match a "word" character (alphanumeric plus "_", plus
other connector punctuation chars plus Unicode
marks)
\W [3] Match a non-"word" character
\s [3] Match a whitespace character
\S [3] Match a non-whitespace character
\d [3] Match a decimal digit character
\D [3] Match a non-digit character
\pP [3] Match P, named property. Use \p{Prop} for longer names
\PP [3] Match non-P
\X [4] Match Unicode "eXtended grapheme cluster"
\1 [5] Backreference to a specific capture group or buffer.
'1' may actually be any positive integer.
\g1 [5] Backreference to a specific or previous group,
\g{-1} [5] The number may be negative indicating a relative
previous group and may optionally be wrapped in
curly brackets for safer parsing.
\g{name} [5] Named backreference
\k<name> [5] Named backreference
\K [6] Keep the stuff left of the \K, don't include it in $&
\N [7] Any character but \n. Not affected by /s modifier
\v [3] Vertical whitespace
\V [3] Not vertical whitespace
\h [3] Horizontal whitespace
\H [3] Not horizontal whitespace
\R [4] Linebreak - [1]
-
Подробности см. в "Bracketed Character Classes" in perlrecharclass.
- [2]
-
Подробности см. в "POSIX Character Classes" in perlrecharclass.
- [3]
-
Подробности см. в "Последовательности обратной косой черты" в perlrecharclass.
- [4]
-
Подробности см. в "Разное" в perlrebackslash.
- [5]
-
Подробности см. в "Группы захвата" ниже.
- [6]
-
Подробности см. в "Расширенные шаблоны" ниже.
- [7]
-
Обратите внимание, что
\Nимеет два значения. Когда он имеет вид\N{NAME}, он соответствует символу или последовательности символов, имя которыхNAME; аналогично, когда он имеет вид\N{U+hex}, он соответствует символу, чей код Unicode — hex. В противном случае он соответствует любому символу, кроме\n. - [8]
-
Подробности см. в "Расширенные скобочные классы символов" в perlrecharclass.
Утверждения
Помимо "^" и "$", Perl определяет следующие утверждения нулевой длины:
\b{} Match at Unicode boundary of specified type
\B{} Match where corresponding \b{} doesn't match
\b Match a \w\W or \W\w boundary
\B Match except at a \w\W or \W\w boundary
\A Match only at beginning of string
\Z Match only at end of string, or before newline at the end
\z Match only at end of string
\G Match only at pos() (e.g. at the end-of-match position
of prior m//g) Граница Unicode (\b{}), доступная начиная с версии 5.22, — это место между двумя символами, или перед первым символом в строке, или после последнего символа в строке, где выполняются определённые критерии, определённые в Unicode. См. "\b{}, \b, \B{}, \B" в perlrebackslash для подробностей.
Граница слова (\b) — это место между двумя символами, имеющее \w с одной стороны и \W с другой стороны (в любом порядке), считая воображаемые символы в начале и конце строки, как соответствующие \W. (Внутри классов символов \b представляет символ обратного удаления, а не границу слова, как обычно в любой строке с двойными кавычками.) \A и \Z аналогичны "^" и "$", за исключением того, что они не будут соответствовать несколько раз, когда используется модификатор /m, в то время как "^" и "$" будут соответствовать каждой внутренней границе строки. Для соответствия фактическому концу строки, а не игнорирования необязательного заключительного символа новой строки, используйте \z.
Утверждение \G может использоваться для цепочек глобальных совпадений (с использованием m//g), как описано в "Regexp Quote-Like Operators" в perlop. Оно также полезно при написании сканеров типа lex, когда у вас есть несколько шаблонов, которые нужно сопоставить с последовательными подстроками вашей строки; см. предыдущую ссылку. Фактическое место, где \G будет соответствовать, также может быть повлияно с использованием pos() в качестве левого операнда: см. "pos" в perlfunc. Обратите внимание, что правило для совпадений нулевой длины (см. "Повторные шаблоны, совпадающие с подстрокой нулевой длины") несколько изменяется, в том, что содержимое слева от \G не учитывается при определении длины совпадения. Таким образом, следующее не будет соответствовать бесконечно:
my $string = 'ABC';
pos($string) = 1;
while ($string =~ /(.\G)/g) {
print $1;
} Будет напечатано 'A', а затем выполнение завершится, так как совпадение считается нулевой длины, и, следовательно, не будет соответствовать в той же позиции дважды подряд.
Стоит отметить, что \G при неправильном использовании может привести к бесконечному циклу. Будьте внимательны при использовании шаблонов, которые включают \G в варианте.
Также обратите внимание, что s/// откажется от перезаписи части подстановки, которая уже была заменена; например, это остановится после первой итерации, а не будет перебирать строку в обратном направлении:
$_ = "123456789";
pos = 6;
s/.(?=.\G)/X/g;
print; # prints 1234X6789, not XXXXX6789 Группы захвата
Конструктор группирования ( ... ) создаёт группы захвата (также называемые буферами захвата). Чтобы сослаться на текущее содержимое группы позже, в том же шаблоне, используйте \g1 (или \g{1}) для первой, \g2 (или \g{2}) для второй и так далее. Это называется обратной ссылкой. Нет ограничений на количество захваченных подстрок, которые вы можете использовать. Группы нумеруются, начиная с левой открывающей скобки, которая имеет номер 1, и т.д. Если группа не сопоставилась, соответствующая обратная ссылка тоже не сопоставится. (Это может произойти, если группа является необязательной или находится в другой ветви альтернативы.) Вы можете опустить "g", и написать "\1", и т.д., но есть некоторые проблемы с этой формой, описанные ниже.
Вы также можете ссылаться на группы захвата относительно, используя отрицательное число, так что \g-1 и \g{-1} относятся к непосредственно предшествующей группе захвата, а \g-2 и \g{-2} относятся к группе перед ней. Например:
/
(Y) # group 1
( # group 2
(X) # group 3
\g{-1} # backref to group 3
\g{-3} # backref to group 1
)
/x будет соответствовать тому же, что и /(Y) ( (X) \g3 \g1 )/x. Это позволяет вам интерполировать регулярные выражения в более крупные регулярные выражения и не беспокоиться о повторной нумерации групп захвата.
Вы можете полностью отказаться от использования чисел и создать именованные группы захвата. Нотация — (?<name>...) для объявления и \g{name} для ссылки. (Для совместимости с регулярными выражениями .Net, \g{name} также может быть записано как \k{name}, \k<name> или \k'name')name не должно начинаться с цифры и не должно содержать дефисов. Когда разные группы в одном шаблоне имеют одно и то же имя, любая ссылка на это имя предполагает левую (самую левую) определённую группу. Именованные группы учитываются в абсолютных и относительных номерах, поэтому их можно также ссылаться с помощью этих номеров. (Существуют возможности для работы с именованными группами захвата, которые в противном случае потребовали бы (??{})).
Содержание группы захвата динамически изменяется и доступно за пределами шаблона до конца окружающего блока или до следующего успешного совпадения, в зависимости от того, что произойдёт раньше. (См. "Составные операторы" в perlsyn.) Вы можете ссылаться на них по абсолютному номеру (используя "$1" вместо "\g1", и т. д); или по имени через хеш %+, используя "$+{name}".
Фигурные скобки необходимы при ссылке на именованные группы захвата, но необязательны для абсолютных или относительных пронумерованных. Фигурные скобки безопаснее при создании регулярного выражения путём конкатенации меньших строк. Например, если у вас есть qr/$a$b/, а $a содержит "\g1", и $b содержит "37", вы получите /\g137/, что, вероятно, не является тем, что вы имели в виду.
Нотации \g и \k были введены в Perl 5.10.0. До этого именованные и относительные пронумерованные группы захвата отсутствовали. Абсолютные пронумерованные группы ссылались с помощью \1, \2, и т. д., и эта нотация по-прежнему поддерживается (и, вероятно, всегда будет). Однако это приводит к некоторым неоднозначностям, если есть более 9 групп захвата, поскольку \10 может означать либо десятую группу захвата, либо символ, порядковый номер которого в восьмеричной системе счисления равен 010 (в ASCII это backspace). Perl разрешает эту неоднозначность, интерпретируя \10 как обратную ссылку только в том случае, если перед ней было открыто не менее 10 левых круглых скобок. Аналогично, \11 является обратной ссылкой только в том случае, если перед ней было открыто не менее 11 левых круглых скобок. И так далее. \1 и \9 всегда интерпретируются как обратные ссылки. Ниже приведены несколько примеров, иллюстрирующих эти опасности. Вы можете избежать неоднозначности, всегда используя \g{} или \g если вы имеете в виду группы захвата; и для восьмеричных констант всегда использовать \o{}, а для \077 и ниже использовать 3 цифры, дополненные ведущими нулями, так как ведущий ноль подразумевает восьмеричную константу.
Нотация \digit также работает в определённых обстоятельствах за пределами шаблона. Подробности см. в разделе "Предупреждение о \1 вместо $1" ниже.
Примеры:
s/^([^ ]*) *([^ ]*)/$2 $1/; # swap first two words
/(.)\g1/ # find first doubled char
and print "'$1' is the first doubled character\n";
/(?<char>.)\k<char>/ # ... a different way
and print "'$+{char}' is the first doubled character\n";
/(?'char'.)\g1/ # ... mix and match
and print "'$1' is the first doubled character\n";
if (/Time: (..):(..):(..)/) { # parse out values
$hours = $1;
$minutes = $2;
$seconds = $3;
}
/(.)(.)(.)(.)(.)(.)(.)(.)(.)\g10/ # \g10 is a backreference
/(.)(.)(.)(.)(.)(.)(.)(.)(.)\10/ # \10 is octal
/((.)(.)(.)(.)(.)(.)(.)(.)(.))\10/ # \10 is a backreference
/((.)(.)(.)(.)(.)(.)(.)(.)(.))\010/ # \010 is octal
$a = '(.)\1'; # Creates problems when concatenated.
$b = '(.)\g{1}'; # Avoids the problems.
"aa" =~ /${a}/; # True
"aa" =~ /${b}/; # True
"aa0" =~ /${a}0/; # False!
"aa0" =~ /${b}0/; # True
"aa\x08" =~ /${a}0/; # True!
"aa\x08" =~ /${b}0/; # False Несколько специальных переменных также ссылаются на части предыдущего совпадения. $+ возвращает то, что соответствовало последней паре квадратных скобок. $& возвращает всю сопоставленную строку. (В какой-то момент $0 также это делал, но сейчас он возвращает имя программы.) $` возвращает всё, что находится перед сопоставленной строкой. $' возвращает всё, что находится после сопоставленной строки. И $^N содержит то, что было сопоставлено наиболее недавно закрытой группой (подстрокой). $^N может использоваться в расширенных шаблонах (см. ниже), например, для присвоения подстроки переменной.
Эти специальные переменные, как хеш %+ и пронумерованные переменные соответствия ($1, $2, $3, и т. д.) динамически изменяются до конца окружающего блока или до следующего успешного совпадения, в зависимости от того, что произойдёт раньше. (См. "Составные операторы" в perlsyn.)
ПРИМЕЧАНИЕ: Неуспешные совпадения в Perl не сбрасывают переменные соответствия, что упрощает написание кода, который проверяет серию более конкретных случаев и запоминает наилучшее соответствие.
ПРЕДУПРЕЖДЕНИЕ: Если ваш код должен выполняться в Perl 5.16 или более ранних версиях, будьте внимательны, так как как только Perl увидит необходимость в $&, $` или $' где-либо в программе, он должен предоставить их для каждого совпадения шаблона. Это может значительно замедлить вашу программу.
Perl использует тот же механизм для создания $1, $2, и т. д, поэтому вы также платите за каждый шаблон, содержащий скобки захвата. (Чтобы избежать этой стоимости, сохранив при этом поведение группирования, используйте расширенное регулярное выражение (?: ... ) вместо него.) Но если вы никогда не используете $&, $` или $', шаблоны без скобок захвата не будут подвергаться штрафу. Поэтому избегайте $&, $' и $`, если можете, но если не можете (а некоторые алгоритмы действительно ценят их), как только вы их использовали один раз, используйте их по своему усмотрению, так как стоимость уже оплачена.
Perl 5.16 ввёл немного более эффективный механизм, который отдельно отмечает, были ли видны каждый из $`, $& и $', и, таким образом, возможно, потребуется скопировать только часть строки. Perl 5.20 представил гораздо более эффективный механизм копирования по запросу, который устраняет любые задержки.
В качестве другого решения этой проблемы Perl 5.10.0 ввёл ${^PREMATCH}, ${^MATCH} и ${^POSTMATCH}, которые эквивалентны $`, $& и $', за исключением того, что они гарантированно определены только после успешного совпадения, выполненного с модификатором /p (сохранение). Использование этих переменных не несёт глобального штрафа за производительность, в отличие от их эквивалентов с пунктуационными знаками, однако в обмен на это вы должны сказать Perl, когда хотите их использовать. Начиная с Perl 5.20, эти три переменные эквивалентны $`, $& и $', а /p игнорируется.
Квалификация метасимволов
Обрамлённые обратным слешем метасимволы в Perl являются буквенно-цифровыми, такими как \b, \w, \n. В отличие от некоторых других языков регулярных выражений, нет обрамлённых обратным слешем символов, которые не являются буквенно-цифровыми. Таким образом, любой символ, похожий на \\, \(, \), \[, \], \{, или \} всегда интерпретируется как буквальный символ, а не метасимвол. Это раньше использовалось в распространённом приёме для отключения или квалификации специальных значений метасимволов регулярных выражений в строке, которую вы хотите использовать в качестве шаблона. Просто квалифицируйте все символы, не являющиеся "словными":
$pattern =~ s/(\W)/\\$1/g; (Если use locale установлено, то это зависит от текущей локали.) Сегодня чаще используется функция quotemeta() или мета-квалифицированная последовательность escape \Q для отключения всех специальных значений метасимволов вот так:
/$unquoted\Q$quoted\E$unquoted/ Будьте внимательны, если вы помещаете буквальные обратные слеши (не те, что внутри интерполированных переменных) между \Q и \E, интерполяция двойных обратных слешей может привести к путанице. Если вам необходимо использовать буквальные обратные слеши внутри \Q...\E, обратитесь к разделу "Подробности синтаксического анализа цитируемых конструкций" в perlop.
quotemeta() и \Q подробно описаны в "quotemeta" в perlfunc.
Расширенные шаблоны
Perl также определяет согласованный синтаксис расширения для функций, отсутствующих в стандартных инструментах, таких как awk и lex. Синтаксис для большинства из них — пара круглых скобок с вопросительным знаком как первой вещью внутри скобок. Символ после вопросительного знака указывает на расширение.
Вопросительный знак был выбран для этого и для минимального соответствия, потому что 1) вопросительные знаки редки в старых регулярных выражениях, и 2) всякий раз, когда вы видите один, вы должны остановиться и "усомниться" в том, что происходит. Это психология...
-
(?#text) -
Комментарий. Текст игнорируется. Обратите внимание, что Perl закрывает комментарий как только видит
")", поэтому нет возможности поместить буквальный")"в комментарий. Закрывающая разделитель шаблона должна быть экранирована обратной косой чертой, если она появляется в комментарии.См. "/x" для другого способа добавления комментариев в шаблоны.
Обратите внимание, что комментарий может быть размещен практически где угодно, кроме середины последовательности экранирования. Примеры:
qr/foo(?#comment)bar/' # Matches 'foobar' # The pattern below matches 'abcd', 'abccd', or 'abcccd' qr/abc(?#comment between literal and its quantifier){1,3}d/ # The pattern below generates a syntax error, because the '\p' must # be followed immediately by a '{'. qr/\p(?#comment between \p and its property name){Any}/ # The pattern below generates a syntax error, because the initial # '\(' is a literal opening parenthesis, and so there is nothing # for the closing ')' to match qr/\(?#the backslash means this isn't a comment)p{Any}/ # Comments can be used to fold long patterns into multiple lines qr/First part of a long regex(?# )remaining part/ -
(?adlupimnsx-imnsx) -
(?^alupimnsx) -
Один или несколько встроенных модификаторов соответствия шаблону, которые нужно включить (или выключить, если перед ними стоит
"-") для остальной части шаблона или остальной части вложенной группы шаблонов (если таковая имеется).Это особенно полезно для динамически генерируемых шаблонов, таких как шаблоны, считываемые из файла конфигурации, из аргумента или из таблицы. Рассмотрим случай, когда некоторые шаблоны должны быть чувствительны к регистру, а некоторые — нет: для нечувствительных к регистру шаблонов достаточно включить
(?i)в начале шаблона. Например:$pattern = "foobar"; if ( /$pattern/i ) { } # more flexible: $pattern = "(?i)foobar"; if ( /$pattern/ ) { }Эти модификаторы восстанавливаются в конце вложенной группы. Например,
( (?i) blah ) \s+ \g1сопоставит
blahв любом случае, некоторые пробелы и точную (включая регистр!) повторение предыдущего слова, при условии наличия модификатора/x, и отсутствия модификатора/iвне этой группы.Эти модификаторы не переносятся в именованные подшаблоны, вызываемые в вложенной группе. Другими словами, шаблон, такой как
((?i)(?&NAME)), не изменяет чувствительность к регистру шаблона"NAME".Модификатор переопределяется последующими появлениями этого конструкта в том же объеме, содержащем тот же модификатор, так что
/((?im)foo(?-m)bar)/сопоставляет все
foobarбез учета регистра, но использует правила/mтолько для частиfoo. Флаг"a"переопределяетaaаналогично,aaпереопределяет"a". То же самое относится к"x"иxx. Следовательно, в/(?-x)foo/xxкак
/x, так и/xxвыключаются во время сопоставленияfoo. И в/(?x)foo/x/xно НЕ/xxвключается для сопоставленияfoo. (Можно ошибочно предположить, что так как внутренний(?x)уже находится в области действия/x, то результат будет эффективно суммой их, давая/xx. Так не работает.) Аналогично, выполнение чего-то вроде(?xx-x)fooотключает все поведение"x"для сопоставленияfoo, это не значит, что вы вычитаете 1"x"из 2, чтобы получить 1"x"оставшегося.Любой из этих модификаторов может быть установлен для глобального применения ко всем регулярным выражениям, скомпилированным в рамках области действия
use re. См. "'/flags' mode" в re.Начиная с Perl 5.14,
"^"(знак каретки или акцент циркумфлекса) сразу после"?"является кратким эквивалентомd-imnsx. Флаги (кроме"d") могут следовать за кареткой, чтобы переопределить её. Но минус-знак не является допустимым.Обратите внимание, что модификаторы
"a","d","l","p"и"u"являются специальными, так как они могут быть только включены, а не выключены, и модификаторы"a","d","l"и"u"взаимно исключают друг друга: указание одного делает другие несущественными, и может появиться не более одного (или двух"a"). Например,(?-p)будет предупреждать при компиляции подuse warnings;(?-d:...)и(?dl:...)являются фатальными ошибками.Также обратите внимание, что модификатор
"p"является особым, так как его наличие в любом месте шаблона имеет глобальный эффект. -
(?:pattern) -
(?adluimnsx-imnsx:pattern) -
(?^aluimnsx:pattern) -
Это для группировки, а не захвата; оно группирует подвыражения, как
"()", но не создаёт обратных ссылок, как"()". Таким образом,@fields = split(/\b(?:a|b|c)\b/)сопоставляет те же разделители полей, что и
@fields = split(/\b(a|b|c)\b/)но не выводит сами разделители в качестве дополнительных полей (хотя такое поведение характерно для "split" в perlfunc, когда его шаблон содержит группы захвата). Также не нужно захватывать символы, если они не нужны.
Любые буквы между
"?"и":"действуют как флаги-модификаторы, как в(?adluimnsx-imnsx). Например,/(?s-i:more.*than).*million/iэквивалентно более подробному
/(?:(?s-i)more.*than).*million/iОбратите внимание, что любые
()конструкции, вложенные в эту, всё ещё будут захватывать, если модификатор/nне включён.Как и конструкция "(?adlupimnsx-imnsx)",
aaи"a"переопределяют друг друга, как иxxи"x". Они не являются аддитивными. Таким образом, выполнение чего-то вроде(?xx-x:foo)отключает всё поведение"x"для сопоставленияfoo.Начиная с Perl 5.14,
"^"(знак каретки или акцент циркумфлекса) сразу после"?"является кратким эквивалентомd-imnsx. Любые положительные флаги (кроме"d") могут следовать за кареткой, поэтому(?^x:foo)эквивалентно
(?x-imns:foo)Каретка сообщает Perl, что эта группа не наследует флаги любого окружающего шаблона, но использует системные значения по умолчанию (
d-imnsx), изменённые любыми указанными флагами.Каретка позволяет упростить строковое представление скомпилированных регулярных выражений. Они выглядят так
(?^:pattern)с любыми флагами, отличными от значений по умолчанию, расположенными между кареткой и двоеточием. Тест, который рассматривает такое строковое представление, не должен иметь жёстко закодированные системные флаги по умолчанию, а только каретку. Если к Perl будут добавлены новые флаги, значение расширения каретки изменится, чтобы включить значение по умолчанию для этих флагов, поэтому тест будет работать, без изменений.
Указание отрицательного флага после каретки является ошибкой, так как флаг избыточен.
Мнемоника для
(?^...): Новое начало, так как обычное использование каретки — это сопоставление в начале. -
(?|pattern) -
Это шаблон «сброса ветвей», который обладает особым свойством, заключающимся в том, что группы захвата нумеруются с той же начальной точки в каждом альтернативном ветвлении. Доступно начиная с perl 5.10.0.
Группы захвата нумеруются слева направо, но внутри этой конструкции нумерация сбрасывается для каждой ветви.
Нумерация внутри каждой ветви будет стандартной, и любые группы, следующие за этим конструктом, будут пронумерованы так, как если бы конструкция содержала только одну ветвь, а именно ту, которая содержит наибольшее количество групп захвата.
Этот конструкт полезен, когда вы хотите захватить одно из нескольких альтернативных совпадений.
Рассмотрим следующий шаблон. Цифры ниже показывают, в какой группе будет храниться захваченное содержимое.
# before ---------------branch-reset----------- after / ( a ) (?| x ( y ) z | (p (q) r) | (t) u (v) ) ( z ) /x # 1 2 2 3 2 3 4Будьте осторожны при использовании шаблона сброса ветвей в сочетании с именованными захватами. Именованные захваты реализуются как псевдонимы к пронумерованным группам, содержащим захваты, и это мешает реализации шаблона сброса ветвей. Если вы используете именованные захваты в шаблоне сброса ветвей, лучше всего использовать те же имена в том же порядке в каждой из альтернатив:
/(?| (?<a> x ) (?<b> y ) | (?<a> z ) (?<b> w )) /xНесоблюдение этого может привести к неожиданным результатам:
"12" =~ /(?| (?<a> \d+ ) | (?<b> \D+))/x; say $+{a}; # Prints '12' say $+{b}; # *Also* prints '12'.Проблема здесь в том, что и группа с именем
a, и группа с именемbявляются псевдонимами группы, принадлежащей$1. - Утверждения оглядывания
-
Ассерции lookaround — это шаблоны нулевой ширины, которые соответствуют определённому шаблону без включения его в
$&. Положительные ассерции соответствуют, когда их подшаблон соответствует, отрицательные ассерции соответствуют, когда их подшаблон не соответствует. Lookbehind соответствует тексту до текущей позиции совпадения, lookahead соответствует тексту после текущей позиции совпадения.-
(?=pattern) -
(*pla:pattern) -
(*positive_lookahead:pattern) -
Ассерция положительного lookahead нулевой ширины. Например,
/\w+(?=\t)/соответствует слову, за которым следует табуляция, без включения табуляции в$&.Алфавитные формы экспериментальные; их использование выводит предупреждение в категории
experimental::alpha_assertions. -
(?!pattern) -
(*nla:pattern) -
(*negative_lookahead:pattern) -
Ассерция отрицательного lookahead нулевой ширины. Например,
/foo(?!bar)/соответствует любому вхождению "foo", за которым не следует "bar". Однако обратите внимание, что lookahead и lookbehind — это НЕ одно и то же. Вы не можете использовать это для lookbehind.Если вы ищете "bar", за которым не следует "foo",
/(?!foo)bar/не сделает того, что вы хотите. Это потому, что(?!foo)просто говорит, что следующее не может быть "foo"—и это не так, это "bar", поэтому "foobar" будет соответствовать. Используйте lookbehind вместо этого (см. ниже).Алфавитные формы экспериментальные; их использование выводит предупреждение в категории
experimental::alpha_assertions. -
(?<=pattern) -
\K -
(*plb:pattern) -
(*positive_lookbehind:pattern) -
Ассерция положительного lookbehind нулевой ширины. Например,
/(?<=\t)\w+/соответствует слову, за которым следует табуляция, без включения табуляции в$&. Работает только для lookbehind фиксированной ширины.Существует специальная форма этого конструкта, называемая
\K(доступная начиная с Perl 5.10.0), которая заставляет движок регулярных выражений "сохранять" всё, что он сопоставил перед\Kи не включать это в$&. Это эффективно обеспечивает lookbehind переменной длины. Использование\Kвнутри другой ассерции lookaround разрешено, но поведение в настоящее время не определено чётко.По различным причинам
\Kможет быть значительно эффективнее, чем эквивалентный конструкт(?<=...), и он особенно полезен в ситуациях, когда вы хотите эффективно удалить что-то, что следует за чем-то другим в строке. Напримерs/(foo)bar/$1/g;может быть переписано как гораздо более эффективное
s/foo\Kbar//g;Алфавитные формы (кроме
\Kявляются экспериментальными; их использование выводит предупреждение в категорииexperimental::alpha_assertions. -
(?<!pattern) -
(*nlb:pattern) -
(*negative_lookbehind:pattern) -
Ассерция отрицательного lookbehind нулевой ширины. Например,
/(?<!bar)foo/соответствует любому вхождению "foo", за которым не следует "bar". Работает только для lookbehind фиксированной ширины.Алфавитные формы экспериментальные; их использование выводит предупреждение в категории
experimental::alpha_assertions.
-
-
(?<NAME>pattern) -
(?'NAME'pattern) -
Именованная группа захвата. Полностью идентична обычным круглым скобкам
()с дополнительной возможностью ссылаться на группу по имени в различных конструкциях регулярных выражений (например,\g{NAME}) и получать доступ к ней по имени после успешного соответствия через%+или%-. См. perlvar для получения дополнительных сведений о массивах%+и%-.Если несколько разных групп захвата имеют одинаковое имя, то
$+{NAME}будет ссылаться на левую группу, определённую в соответствии.Формы
(?'NAME'pattern)и(?<NAME>pattern)эквивалентны.ПРИМЕЧАНИЕ: Хотя запись этого конструкта такая же, как у аналогичной функции в .NET регулярных выражениях, поведение отличается. В Perl группы нумеруются последовательно независимо от того, являются ли они именованными или нет. Таким образом, в шаблоне
/(x)(?<foo>y)(z)/$+{foo}будет таким же, как$2, и$3будет содержать 'z' вместо обратного, чего мог бы ожидать хакер .NET регулярных выражений.В настоящее время NAME ограничен только простыми идентификаторами. Другими словами, он должен соответствовать
/^[_A-Za-z][_A-Za-z0-9]*\z/или его расширению Юникода (см. utf8), хотя он не расширяется локалью (см. perllocale).ПРИМЕЧАНИЕ: Чтобы облегчить работу программистам, знакомым с движками регулярных выражений Python или PCRE, вместо
(?<NAME>pattern)можно использовать шаблон(?P<NAME>pattern); однако эта форма не поддерживает использование одинарных кавычек в качестве разделителя имени. -
\k<NAME> -
\k'NAME' -
Именованная ссылка на обратную ссылку. Аналогично числовым обратным ссылкам, за исключением того, что группа обозначается именем, а не номером. Если несколько групп имеют одинаковое имя, оно ссылается на левую определённую группу в текущем соответствии.
Ошибка ссылаться на имя, не определённое с помощью
(?<NAME>)ранее в шаблоне.Обе формы эквивалентны.
ПРИМЕЧАНИЕ: Чтобы облегчить работу программистам, знакомым с движками регулярных выражений Python или PCRE, вместо
\k<NAME>можно использовать шаблон(?P=NAME). -
(?{ code }) -
ПРЕДУПРЕЖДЕНИЕ: Безопасное использование этой функции требует понимания её ограничений. Выполняемый код с побочными эффектами может не выполнять одинаковые действия от версии к версии из-за влияния будущих оптимизаций движка регулярных выражений. Для получения более подробной информации об этом, см. "Частота выполнения встраиваемого кода".
Эта ассерция нулевой ширины выполняет любой встраиваемый Perl-код. Она всегда выполняется успешно, а её возвращаемое значение устанавливается как
$^R.В литеральных шаблонах код разбирается одновременно с окружающим кодом. Внутри шаблона управление временно передаётся обратно парсеру Perl, до тех пор, пока не будет встречена закрывающая логически-сбалансированная фигурная скобка. Это аналогично тому, как обрабатывается выражение индекса массива в литеральной строке, например
"abc$array[ 1 + f('[') + g()]def"В частности, фигурные скобки не обязательно должны быть сбалансированы:
s/abc(?{ f('{'); })/def/Даже в шаблоне, который интерполируется и компилируется во время выполнения, литеральные блоки кода будут скомпилированы один раз, во время компиляции Perl; следующее выведет "ABCD":
print "D"; my $qr = qr/(?{ BEGIN { print "A" } })/; my $foo = "foo"; /$foo$qr(?{ BEGIN { print "B" } })/; BEGIN { print "C" }В шаблонах, где текст кода получен из информации времени выполнения, а не появляется буквально в исходном коде /шаблоне/, код компилируется одновременно с компиляцией шаблона, и по соображениям безопасности
use re 'eval'должен находиться в области видимости. Это для того, чтобы предотвратить выполнение кода из пользовательских шаблонов, содержащих фрагменты кода.В ситуациях, когда вам нужно включить это с помощью
use re 'eval', вы также должны включить проверку нарушения целостности. Лучше всего использовать тщательно ограниченное вычисление в безопасном отсеке. См. perlsec для получения подробностей о каждом из этих механизмов.С точки зрения разбора, области видимости лексических переменных и замыканий
/AAA(?{ BBB })CCC/поведение примерно такое же, как
/AAA/ && do { BBB } && /CCC/Аналогично
qr/AAA(?{ BBB })CCC/поведение примерно такое же, как
sub { /AAA/ && do { BBB } && /CCC/ }В частности:
{ my $i = 1; $r = qr/(?{ print $i })/ } my $i = 2; /$r/; # prints "1"Внутри блока
(?{...}),$_ссылается на строку, с которой сопоставляется регулярное выражение. Вы также можете использоватьpos()для того, чтобы узнать текущую позицию соответствия в этой строке.Блок кода вводит новую область видимости с точки зрения объявлений лексических переменных, но не с точки зрения
localи аналогичных локальных свойств. Следовательно, более поздние блоки кода в том же шаблоне всё ещё будут видеть значения, которые были локализованы в предыдущих блоках. Эти накопленные локализации отменяются либо по окончании успешного соответствия, либо при возврате назад (см. "Возврат назад"). Например,$_ = 'a' x 8; m< (?{ $cnt = 0 }) # Initialize $cnt. ( a (?{ local $cnt = $cnt + 1; # Update $cnt, # backtracking-safe. }) )* aaaa (?{ $res = $cnt }) # On success copy to # non-localized location. >x;сначала увеличит
$cntдо 8; затем во время возврата назад его значение будет уменьшено обратно до 4, что является значением, присвоенным$res. В конце выполнения регулярного выражения$cntбудет уменьшено до первоначального значения 0.Эта ассерция может использоваться в качестве условия в
(?(condition)yes-pattern|no-pattern)переключателе. Если она не используется таким образом, результат вычисления
codeпомещается в специальную переменную$^R. Это происходит немедленно, поэтому$^Rможет использоваться из других(?{ code })ассерций внутри того же регулярного выражения.Присвоение
$^Rвыше правильно локализовано, поэтому старое значение$^Rвосстанавливается, если ассерция возвращается назад; см. "Возврат назад".Обратите внимание, что специальная переменная
$^Nособенно полезна в блоках кода для захвата результатов подсоответствий в переменные без необходимости отслеживания количества вложенных круглых скобок. Например:$_ = "The brown fox jumps over the lazy dog"; /the (\S+)(?{ $color = $^N }) (\S+)(?{ $animal = $^N })/i; print "color = $color, animal = $animal\n"; -
(??{ code })
-
ПРЕДУПРЕЖДЕНИЕ: Безопасное использование этой функции требует понимания её ограничений. Выполняемый код, имеющий побочные эффекты, может не работать одинаково в разных версиях из-за влияния будущих оптимизаций в движке регулярных выражений. Для получения дополнительной информации об этом см. «Частота выполнения встроенного кода».
Это «отложенное» подвыражение регулярного выражения. Оно ведёт себя точно так же, как блок кода
(?{ code }), описанный выше, за исключением того, что его возвращаемое значение, вместо присваивания$^R, обрабатывается как шаблон, компилируется, если это строка (или используется как есть, если это объект qr//), а затем сравнивается, как будто он вставлен вместо этого конструкта.Во время сравнения этого подвыражения у него есть свой набор захватов, которые действительны во время подсравнения, но отбрасываются после возвращения управления к основному шаблону. Например, следующее совпадает, при этом внутренний шаблон захватывает «B» и совпадает с «BB», а внешний шаблон захватывает «A»;
my $inner = '(.)\1'; "ABBA" =~ /^(.)(??{ $inner })\1/; print $1; # prints "A";Обратите внимание, что это означает, что внутренний шаблон не может ссылаться на группу захвата, определённую снаружи. (Сам блок кода может использовать
$1, и т. д., для ссылки на группы захвата окружающего шаблона.) Таким образом, хотя('a' x 100)=~/(??{'(.)' x 100})/будет совпадать, но не установит
$1при выходе.Следующий шаблон совпадает с группой в скобках:
$re = qr{ \( (?: (?> [^()]+ ) # Non-parens without backtracking | (??{ $re }) # Group with matching parens )* \) }x;См. также
(?PARNO)для другого, более эффективного способа выполнения той же задачи.Выполнение отложенного регулярного выражения слишком много раз без потребления какой-либо входной строки также приведёт к ошибке. Глубина, на которой это происходит, компилируется в Perl, поэтому её можно изменить с помощью пользовательской сборки.
-
(?PARNO)(?-PARNO)(?+PARNO)(?R)(?0) -
Рекурсивное подвыражение. Обработайте содержимое заданного буфера захвата в текущем шаблоне как независимое подвыражение и попытайтесь сопоставить его с текущей позицией в строке. Подвыражение может получить информацию о состоянии захвата от вызывающего объекта, например, для обратных ссылок, но буферы захвата, заданные подвыражением, не видны вызывающему объекту.
Аналогично
(??{ code })за исключением того, что оно не включает выполнение какого-либо кода или потенциальную компиляцию возвращаемой строки шаблона; вместо этого оно обрабатывает часть текущего шаблона, содержащуюся внутри указанной группы захвата, как независимый шаблон, который должен совпадать с текущей позицией. Также отличается обработка буферов захвата, в отличие от(??{ code })рекурсивных шаблонов имеют доступ к состоянию совпадения своего вызывающего объекта, поэтому можно безопасно использовать обратные ссылки.PARNO — это последовательность цифр (не начинающаяся с 0), значение которой отражает номер скобок группы захвата, к которой требуется рекурсия.
(?R)выполняет рекурсию к началу всего шаблона.(?0)— это альтернативная синтаксическая конструкция для(?R). Если PARNO предшествует знак «плюс» или «минус», то предполагается, что это относительно, причём отрицательные числа указывают на предыдущие группы захвата, а положительные — на последующие. Таким образом,(?-1)относится к последней объявленной группе, а(?+1)указывает на следующую объявленную группу. Обратите внимание, что счёт для относительной рекурсии отличается от учёта для относительных обратных ссылок, поскольку в рекурсии незакрытые группы включаются.Следующий шаблон соответствует функции
foo(), которая может содержать сбалансированные скобки в качестве аргумента.$re = qr{ ( # paren group 1 (full function) foo ( # paren group 2 (parens) \( ( # paren group 3 (contents of parens) (?: (?> [^()]+ ) # Non-parens without backtracking | (?2) # Recurse to start of paren group 2 )* ) \) ) ) }x;Если шаблон использовался следующим образом
'foo(bar(baz)+baz(bop))'=~/$re/ and print "\$1 = $1\n", "\$2 = $2\n", "\$3 = $3\n";выход должен быть следующим:
$1 = foo(bar(baz)+baz(bop)) $2 = (bar(baz)+baz(bop)) $3 = bar(baz)+baz(bop)Если соответствующая группа захвата не определена, то это ошибка. Рекурсия на большую глубину без потребления входной строки также приведёт к ошибке. Глубина, на которой это происходит, компилируется в Perl, поэтому её можно изменить с помощью пользовательской сборки.
Следующее показывает, как использование отрицательного индексирования может облегчить встраивание рекурсивных шаблонов внутри
qr//конструкта для последующего использования:my $parens = qr/(\((?:[^()]++|(?-1))*+\))/; if (/foo $parens \s+ \+ \s+ bar $parens/x) { # do something here... }Примечание, что этот шаблон ведет себя не так, как эквивалентные конструкции PCRE или Python той же формы. В Perl вы можете выполнить обратный откат в рекурсивную группу, в PCRE и Python рекурсивно захваченная группа обрабатывается как атомарная. Кроме того, модификаторы разрешаются во время компиляции, поэтому конструкции типа
(?i:(?1))или(?:(?i)(?1))не влияют на обработку подвыражения. -
(?&NAME) -
Рекурсия к именованному подвыражению. Идентично
(?PARNO)за исключением того, что скобки для рекурсии определяются по имени. Если несколько скобок имеют одинаковое имя, то происходит рекурсия к самой левой.Ссылка на имя, которое не объявлено где-либо в шаблоне, является ошибкой.
ПРИМЕЧАНИЕ: Чтобы облегчить программистам, знакомым с движками регулярных выражений Python или PCRE, может использоваться шаблон
(?P>NAME)вместо(?&NAME). -
(?(condition)yes-pattern|no-pattern) -
(?(condition)yes-pattern) -
Условное выражение. Совпадает с
yes-pattern, еслиconditionвозвращает истинное значение, в противном случае совпадает сno-pattern. Отсутствие шаблона всегда совпадает.(condition)должно быть одним из:- целое число в скобках
-
(что является допустимым, если соответствующая пара скобок совпала);
- оператор предпросмотра/оператор предпросмотра-обратный ход/выражение нулевой ширины;
- имя в угловых скобках или одинарных кавычках
-
(что является допустимым, если группа с заданным именем совпала);
-
специальный символ
(R) -
(истина, когда вычисляется внутри рекурсии или eval). Кроме того,
"R"может быть после цифры (что будет истинным, когда вычисляется при рекурсии внутри соответствующей группы) или после&NAME, в этом случае она будет истинна только при вычислении во время рекурсии в именованной группе.
Вот сводка возможных предикатов:
-
(1)(2)... -
Проверяет, совпала ли пронумерованная группа захвата с чем-либо. Полный синтаксис:
(?(1)then|else) -
(<NAME>)('NAME') -
Проверяет, совпала ли группа с заданным именем с чем-либо. Полный синтаксис:
(?(<name>)then|else) -
(?=...)(?!...)(?<=...)(?<!...) -
Проверяет, соответствует ли шаблон (или не соответствует, для
"!"вариантов). Полный синтаксис:(?(?=lookahead)then|else) -
(?{ CODE }) -
Обрабатывает возвращаемое значение блока кода как условие. Полный синтаксис:
(?(?{ code })then|else) -
(R) -
Проверяет, вычислялось ли выражение внутри рекурсии. Полный синтаксис:
(?(R)then|else) -
(R1)(R2)... -
Проверяет, вычислялось ли выражение во время выполнения непосредственно внутри n-й группы захвата. Эта проверка — это эквивалент регулярных выражений
if ((caller(0))[3] eq 'subname') { ... }Другими словами, она не проверяет весь стек рекурсии.
Полный синтаксис:
(?(R1)then|else) -
(R&NAME) -
Аналогично
(R1), этот предикат проверяет, выполняем ли мы непосредственное выполнение внутри самой левой группы с заданным именем (эта логика используется(?&NAME)для устранения неоднозначности). Он не проверяет весь стек, а только имя самого внутреннего активного рекурсивного вызова. Полный синтаксис:(?(R&name)then|else) -
(DEFINE) -
В этом случае yes-шаблон никогда напрямую не выполняется, и no-шаблон не допускается. Похоже по духу на
(?{0}), но более эффективно. Подробности см. ниже. Полный синтаксис:(?(DEFINE)definitions...)
Например:
m{ ( \( )? [^()]+ (?(1) \) ) }xсоответствует куску без скобок, возможно, включённому в сами скобки.
Особой формой является предикат
(DEFINE), который никогда напрямую не выполняет yes-шаблон и не допускает no-шаблон. Это позволяет определить подвыражения, которые будут выполняться только механизмом рекурсии. Таким образом, вы можете определить набор правил регулярных выражений, которые можно объединить в любой выбранный вами шаблон.Рекомендуется поместить блок DEFINE в конец шаблона и назвать все подвыражения, определённые в нём.
Также стоит отметить, что определённые таким образом шаблоны, вероятно, не будут такими эффективными, так как оптимизатор не очень умён при работе с ними.
Пример использования:
/(?<NAME>(?&NAME_PAT))(?<ADDR>(?&ADDRESS_PAT)) (?(DEFINE) (?<NAME_PAT>....) (?<ADDRESS_PAT>....) )/xОбратите внимание, что группы захвата, согласованные внутри рекурсии, недоступны после возвращения из рекурсии, поэтому необходим дополнительный уровень групп захвата. Таким образом,
$+{NAME_PAT}не было бы определено, хотя$+{NAME}было бы.Наконец, помните, что подвыражения, созданные внутри блока DEFINE, учитываются в абсолютном и относительном количестве захватов, поэтому это:
my @captures = "a" =~ /(.) # First capture (?(DEFINE) (?<EXAMPLE> 1 ) # Second capture )/x; say scalar @captures;Выведет 2, а не 1. Это особенно важно, если вы планируете компилировать определения с помощью оператора
qr//и впоследствии интерполировать их в другой шаблон. -
(?>pattern) -
(*atomic:pattern)
-
Подвыражение «независимое», которое соответствует подстроке, которую бы соответствовало самостоятельное
pattern, если бы оно было привязано к заданной позиции, и оно соответствует только этой подстроке. Этот конструкт полезен для оптимизации того, что в противном случае были бы «вечные» совпадения, потому что он не будет отступать (см. «Откатывание»). Он также может быть полезен в тех местах, где желаема семантика «захват всего, что вы можете, и ничего не отдавать».Например:
^(?>a*)abникогда не будет соответствовать, так как(?>a*)(привязанное к началу строки, как указано выше) будет соответствовать всем символам"a"в начале строки, не оставляя"a"дляabдля соответствия. В противоположность этомуa*abбудет соответствовать тому же, что иa+b, так как соответствие подгруппыa*зависит от следующей группыab(см. «Откатывание»). В частности,a*внутриa*abбудет соответствовать меньшему количеству символов, чем самостоятельноеa*, поскольку это приводит к соответствию хвоста.(?>pattern)не отключает откатывание полностью после того, как оно сошлось. Возвращение назад за конструкт все еще возможно, но не в него. Таким образом,((?>a*)|(?>b*))arвсе равно будет соответствовать «bar».Эффект, аналогичный
(?>pattern), можно получить, написав(?=(pattern))\g{-1}. Это соответствует той же подстроке, что и самостоятельноеa+, а следующее\g{-1}съедает сопоставленную строку; это, следовательно, превращает утверждение нулевой длины в аналог(?>...). (Различие между этими двумя конструкциями заключается в том, что второй использует группу захвата, тем самым смещая порядковые номера обратных ссылок в остальной части регулярного выражения.)Рассмотрим этот шаблон:
m{ \( ( [^()]+ # x+ | \( [^()]* \) )+ \) }xЭто эффективно соответствует непустой группе с соответствующими скобками глубиной в два уровня или меньше. Однако, если такой группы нет, это займет практически вечность на длинной строке. Это происходит из-за большого количества способов разделить длинную строку на несколько подстрок. Именно это делает
(.+)+, и(.+)+аналогично подшаблону вышеприведенного шаблона. Обратите внимание, как шаблон выше обнаруживает отсутствие совпадения на((()aaaaaaaaaaaaaaaaaaза несколько секунд, но каждый дополнительный символ удваивает это время. Эта экспоненциальная производительность заставит вас подумать, что ваша программа зависла. Однако небольшая модификация этого шаблонаm{ \( ( (?> [^()]+ ) # change x+ above to (?> x+ ) | \( [^()]* \) )+ \) }xкоторый использует
(?>...)соответствует точно так же, как и предыдущий (проверьте это самостоятельно, это будет полезным упражнением), но завершается в четыре раза быстрее при использовании на похожей строке с 1000000"a". Однако имейте в виду, что когда этот конструкт следует за квантификатором, он в настоящее время выводит сообщение об ошибке под псевдонимомuse warningsили переключателем -w, говорящее, что"matches null string many times in regex".В случае простых групп, таких как шаблон
(?> [^()]+ ), аналогичный эффект может быть достигнут с помощью отрицательного предпросмотра, как в[^()]+ (?! [^()] ). Это было всего в 4 раза медленнее на строке с 1000000"a".Семантика «захват всего, что вы можете, и ничего не отдавать» желательна во многих ситуациях, когда на первый взгляд простое
()*кажется правильным решением. Предположим, мы анализируем текст, где комментарии ограничены"#"и за которыми следует необязательное (горизонтальное) пробельное пространство. Вопреки внешнему виду,#[ \t]*не является правильным подвыражением для соответствия разделителю комментариев, потому что он может «отказаться» от некоторого пробельного пространства, если остаток шаблона может быть согласован таким образом. Правильный ответ — либо один из следующих:(?>#[ \t]*) #[ \t]*(?![ \t])Например, для захвата непустых комментариев в
$1следует использовать один из этих вариантов:/ (?> \# [ \t]* ) ( .+ ) /x; / \# [ \t]* ( [^ \t] .* ) /x;Выбор зависит от того, какой из этих выражений лучше отражает приведенное выше определение комментариев.
В некоторых источниках этот конструкт называется «атомным сопоставлением» или «положительным сопоставлением».
Положительные квантификаторы эквивалентны помещению элемента, к которому они применяются, внутрь одного из этих конструктов. Применимы следующие эквивалентности:
Quantifier Form Bracketing Form --------------- --------------- PAT*+ (?>PAT*) PAT++ (?>PAT+) PAT?+ (?>PAT?) PAT{min,max}+ (?>PAT{min,max})Вложенные
(?>...)конструкции не являются бесполезными, даже если на первый взгляд они могут показаться таковыми. Это потому, что вложенные(?>...)могут ограничивать внутренние откаты, которые в противном случае могли бы произойти. Например,"abc" =~ /(?>a[bc]*c)/соответствует, но
"abc" =~ /(?>a(?>[bc]*)c)/не соответствует.
Алфавитный вариант (
(*atomic:...)) экспериментальный; его использование приводит к предупреждению в категорииexperimental::alpha_assertions. -
(?[ ]) -
См. «Расширенные символьные классы в квадратных скобках» в perlrecharclass.
Обратите внимание, что эта функция в настоящее время экспериментальная; ее использование приводит к предупреждению в категории
experimental::regex_sets.
Откатывание
ПРИМЕЧАНИЕ: Этот раздел представляет абстрактное приближение поведения регулярных выражений. Для более строгого (и сложного) представления правил, участвующих в выборе совпадения среди возможных альтернатив, см. «Объединение элементов RE».
Фундаментальная особенность сопоставления регулярных выражений включает понятие откатывания, которое в настоящее время используется (по необходимости) всеми регулярными не-положительными квантификаторами выражений, а именно "*", *?, "+", +?, {n,m}, и {n,m}?. Откатывание часто оптимизируется внутри, но общий принцип, описанный здесь, справедлив.
Для соответствия регулярного выражения необходимо соответствие всего регулярного выражения, а не только его части. Таким образом, если начало шаблона, содержащего квантификатор, успешно приводит к тому, что последующие части шаблона терпят неудачу, движок сопоставления отступает и пересчитывает начальную часть — вот почему это называется откатыванием.
Вот пример откатывания: Предположим, вы хотите найти слово, следующее за «foo» в строке «Food is on the foo table»:
$_ = "Food is on the foo table.";
if ( /\b(foo)\s+(\w+)/i ) {
print "$2 follows $1.\n";
} При выполнении сопоставления первая часть регулярного выражения (\b(foo)) находит возможное соответствие прямо в начале строки и загружает $1 со значением «Foo». Однако как только движок сопоставления видит, что после «Foo», которое он сохранил в $1, нет пробела, он понимает свою ошибку и начинает сначала на один символ после того места, где у него было предварительное соответствие. На этот раз он доходит до следующего вхождения «foo». Вся регулярное выражение в этот раз совпадает, и вы получаете ожидаемый вывод «table follows foo».
Иногда минимальное соответствие может очень помочь. Представьте, что вам нужно сопоставить все между «foo» и «bar». Вначале вы пишете что-то вроде этого:
$_ = "The food is under the bar in the barn.";
if ( /foo(.*)bar/ ) {
print "got <$1>\n";
} Что, возможно, неожиданно приводит к:
got <d is under the bar in the > Это происходит потому, что .* был жадным, поэтому вы получаете всё между первым «foo» и последним «bar». Здесь эффективнее использовать минимальное соответствие, чтобы убедиться, что вы получаете текст между «foo» и первым последующим «bar».
if ( /foo(.*?)bar/ ) { print "got <$1>\n" }
got <d is under the > Вот ещё один пример. Предположим, вам нужно сопоставить число в конце строки, и вы также хотите сохранить предшествующую часть соответствия. Вы напишете это:
$_ = "I have 2 numbers: 53147";
if ( /(.*)(\d*)/ ) { # Wrong!
print "Beginning is <$1>, number is <$2>.\n";
} Это не сработает вообще, потому что .* был жадным и проглотил всю строку. Так как \d* может соответствовать пустой строке, всё регулярное выражение успешно сопоставлено.
Beginning is <I have 2 numbers: 53147>, number is <>. Вот несколько вариантов, большинство из которых не работают:
$_ = "I have 2 numbers: 53147";
@pats = qw{
(.*)(\d*)
(.*)(\d+)
(.*?)(\d*)
(.*?)(\d+)
(.*)(\d+)$
(.*?)(\d+)$
(.*)\b(\d+)$
(.*\D)(\d+)$
};
for $pat (@pats) {
printf "%-12s ", $pat;
if ( /$pat/ ) {
print "<$1> <$2>\n";
} else {
print "FAIL\n";
}
} Это напечатает:
(.*)(\d*) <I have 2 numbers: 53147> <>
(.*)(\d+) <I have 2 numbers: 5314> <7>
(.*?)(\d*) <> <>
(.*?)(\d+) <I have > <2>
(.*)(\d+)$ <I have 2 numbers: 5314> <7>
(.*?)(\d+)$ <I have 2 numbers: > <53147>
(.*)\b(\d+)$ <I have 2 numbers: > <53147>
(.*\D)(\d+)$ <I have 2 numbers: > <53147> Как видите, это может быть немного сложно. Важно понять, что регулярное выражение — это всего лишь набор утверждений, которые определяют успех. Может быть 0, 1 или несколько способов, которыми определение может увенчаться успехом в отношении конкретной строки. И если есть несколько способов, которыми это может получиться, вам необходимо понять откатывание, чтобы знать, какой вариант успеха вы получите.
При использовании утверждений и отрицаний просмотров это может стать ещё сложнее. Представьте, что вы хотите найти последовательность нецифр, за которой не следует «123». Вы можете попытаться написать это как:
$_ = "ABC123";
if ( /^\D*(?!123)/ ) { # Wrong!
print "Yup, no 123 in $_\n";
} Но это не сработает; по крайней мере, не так, как вы надеялись. Она утверждает, что в строке нет 123. Вот более ясная картина того, почему этот шаблон соответствует, вопреки распространённым ожиданиям:
$x = 'ABC123';
$y = 'ABC445';
print "1: got $1\n" if $x =~ /^(ABC)(?!123)/;
print "2: got $1\n" if $y =~ /^(ABC)(?!123)/;
print "3: got $1\n" if $x =~ /^(\D*)(?!123)/;
print "4: got $1\n" if $y =~ /^(\D*)(?!123)/; Это напечатает
2: got ABC
3: got AB
4: got ABC Вы могли бы ожидать, что тест 3 не пройдёт, потому что он кажется более общей версией теста 1. Важное различие между ними в том, что тест 3 содержит квантификатор (\D*) и поэтому может использовать откатывание, в то время как тест 1 этого не сделает. Происходит следующее: вы спросили: «Это правда, что в начале $x, после 0 или более нецифр, у вас есть что-то, что не является 123?» Если движок сопоставления шаблонов разрешил \D* расшириться до «ABC», это привело бы к провалу всего шаблона.
Поисковый движок сначала сопоставит \D* с «ABC». Затем он попытается сопоставить (?!123) с «123», что терпит неудачу. Но поскольку в регулярном выражении используется квантификатор (\D*), движок поиска может отступить и повторить поиск таким образом, чтобы, возможно, сопоставить все регулярное выражение.
Шаблон действительно, действительно хочет добиться успеха, поэтому он использует стандартный механизм отступления и повторной попытки, и на этот раз позволяет \D* расшириться до «AB». Теперь за «AB» действительно следует что-то, что не является «123». Это «C123», что достаточное условие.
Мы можем справиться с этим, используя как утверждение, так и отрицание. Мы скажем, что первая часть в $1 должна следовать как за цифрой, так и за чем-то, что не является «123». Помните, что утверждения просмотров — выражения нулевой ширины — они только смотрят, но не потребляют никакой части строки в их совпадении. Таким образом, переписывание таким образом даёт то, что вы ожидали; то есть, случай 5 будет неудачным, а случай 6 успешным:
print "5: got $1\n" if $x =~ /^(\D*)(?=\d)(?!123)/;
print "6: got $1\n" if $y =~ /^(\D*)(?=\d)(?!123)/;
6: got ABC Другими словами, два утверждения нулевой ширины рядом друг с другом работают так, как будто они соединены логическим И, как вы бы использовали любые встроенные утверждения: /^$/ совпадает только тогда, когда вы находитесь в начале строки И в конце строки одновременно. Более глубокая истина заключается в том, что смежные элементы в регулярных выражениях всегда означают И, за исключением случаев, когда вы пишите явное ИЛИ с помощью вертикальной черты. /ab/ означает сопоставить «a» И (затем) сопоставить «b», хотя попытки сопоставления производятся в разных позициях, так как «a» не утверждение нулевой ширины, а утверждение единичной ширины.
ПРЕДУПРЕЖДЕНИЕ: Особенные сложные регулярные выражения могут занимать экспоненциальное время для решения из-за огромного числа возможных способов, которыми они могут использовать обратную подстановку для поиска совпадения. Например, без внутренних оптимизаций, выполненных движком регулярных выражений, это займет очень много времени:
'aaaaaaaaaaaa' =~ /((a{0,5}){0,5})*[c]/ И если бы вы использовали "*" в внутренних группах вместо ограничения их до 0 до 5 совпадений, то это заняло бы вечность — или до тех пор, пока у вас не закончилось бы место в стеке. Более того, эти внутренние оптимизации не всегда применимы. Например, если вы поставили {0,5} вместо "*" во внешней группе, никакая текущая оптимизация не применима, и совпадение занимает много времени.
Мощным инструментом для оптимизации таких зверей является то, что известно как «независимая группа», которая не выполняет обратную подстановку (см. "(?>pattern)"). Также обратите внимание, что утверждения нулевой длины lookahead/lookbehind не будут выполнять обратную подстановку, чтобы сделать соответствие хвоста, так как они находятся в «логическом» контексте: учитывается только то, совпадают они или нет. Пример, где побочные эффекты lookahead могут повлиять на следующее соответствие, см. "(?>pattern)".
Скриптовые последовательности
Скриптовая последовательность — это в основном последовательность символов, все из одного и того же сценария Юникода (см. "Сценарии" в perlunicode), например, латинского или греческого. В большинстве мест одно слово никогда не записывалось бы на нескольких сценариях, если это не атака подделки. Пример печально известный
paypal.com Эти буквы могут быть все латинскими (как в приведённом выше примере), или все кириллическими (за исключением точки), или их может быть смесью двух. В случае интернет-адреса .com будет на латинице, а любые кириллические буквы будут указывать на смесь, а не на последовательность сценариев. Человек, нажав на такую ссылку, не будет перенаправлен на реальный сайт PayPal, но злоумышленник создаст похожий, чтобы попытаться собрать конфиденциальную информацию.
Начиная с Perl 5.28, теперь легко обнаруживать строки, которые не являются скриптовыми последовательностями. Просто заключите практически любой шаблон, как один из этих:
(*script_run:pattern)
(*sr:pattern) Что происходит, это то, что после того, как шаблон успешно совпадает, он подвергается дополнительному критерию, что каждый символ в нём должен быть из одного и того же сценария (см. исключения ниже). Если это не так, происходит обратная подстановка до тех пор, пока не будет найдено что-то, всё в одном сценарии, что соответствует, или пока все возможности не будут исчерпаны. Это может вызвать много обратных вставок, но, как правило, только вредоносный ввод может привести к этому, хотя замедление может вызвать атаку отказа в обслуживании. Если ваши потребности позволяют, лучше сделать шаблон атомным. Это, скорее всего, то, что вам нужно, поэтому вместо того, чтобы писать это:
(*script_run:(?>pattern)) вы можете написать так:
(*atomic_script_run:pattern)
(*asr:pattern) (см. "(?>pattern)".)
В Тайване, Японии и Корее обычно текст имеет смесь символов из своих родных сценариев и базового китайского. Perl следует механизмам безопасности Юникода UTS 39 (http://unicode.org/reports/tr39/), разрешая такие смеси.
Правила, используемые для сопоставления десятичных цифр, несколько строже. Многие сценарии имеют свои собственные наборы цифр, эквивалентные западным 0 и 9. Несколько, например, арабские, имеют более одного набора. Чтобы строка считалась скриптовой последовательностью, все цифры в ней должны происходить из одного и того же набора из десяти, как определено первой встреченной цифрой. Как пример,
qr/(*script_run: \d+ \b )/x гарантирует, что все сопоставленные цифры будут взяты из одного и того же набора из 10. Вы не получите похожую цифру из другого сценария, которая имеет другое значение, чем то, что она представляется.
Юникод имеет три псевдо-сценария, которые обрабатываются специально.
«Неизвестно» применяется к кодовым точкам, смысл которых ещё предстоит определить. В настоящее время Perl будет соответствовать как скриптовой последовательности любой строке из одного символа, состоящей из одной из этих кодовых точек. Но любая строка длиннее одной кодовой точки, содержащая одну из них, не будет считаться скриптовой последовательностью.
«Унаследованный» применяется к символам, которые изменяют другой, например, ударение какого-либо типа. Они считаются частью сценария основного символа и поэтому никогда не вызывают несоответствия скриптовой последовательности.
Другой — «Общий». Он состоит в основном из знаков препинания, эмодзи и символов, используемых в математике и музыке, ASCII-цифрах 0 и 9, а также полных форм этих цифр. Эти символы могут встречаться вперемешку в текстах во многих сценариях мира. Они также не приводят к несоответствию скриптовой последовательности. Но, как и другие сценарии, все цифры в последовательности должны быть из одного и того же набора из 10.
Этот конструкт не захватывает. Вы можете добавить скобки к шаблону для захвата, если хотите. Вам придётся это сделать, если вы планируете использовать "(*ACCEPT) (*ACCEPT:arg)" и не хотите, чтобы он игнорировал проверку скриптовой последовательности.
Эта функция экспериментальная, и точный синтаксис и детали работы могут быть изменены; её использование выводит предупреждение в категории experimental::script_run.
Свойство Script_Extensions используется в качестве основы для этой функции.
Специальные управляющие вербы обратной подстановки
Эти специальные шаблоны, как правило, имеют вид (*VERB:ARG). Если не указано иное, аргумент ARG необязателен; в некоторых случаях он обязателен.
Любой шаблон, содержащий специальную управляющую вербу обратной подстановки, которая допускает аргумент, имеет специальное поведение: при выполнении он устанавливает переменные текущего пакета $REGERROR и $REGMARK. При этом применяются следующие правила:
При ошибке переменная $REGERROR будет установлена в значение ARG шаблона вербы, если верба была вовлечена в ошибку совпадения. Если часть ARG шаблона была опущена, то $REGERROR будет установлена в имя последнего шаблона (*MARK:NAME) который был выполнен, или в TRUE, если его не было. Кроме того, переменная $REGMARK будет установлена в FALSE.
При успешном совпадении переменная $REGERROR будет установлена в FALSE, а переменная $REGMARK — в имя последнего шаблона (*MARK:NAME) который был выполнен. Подробности см. в объяснении вербы (*MARK:NAME) ниже.
ПРИМЕЧАНИЕ: $REGERROR и $REGMARK — не магические переменные, такие как $1 и большинство других переменных, связанных с регулярными выражениями. Они не локальны для области видимости и не являются только для чтения, а вместо этого являются динамичными переменными пакета, аналогичными $AUTOLOAD. Они устанавливаются в пакете, содержащем код, который выполнил регулярное выражение (а не тот, который его скомпилировал, если они отличаются). При необходимости вы можете использовать local для локализации изменений этих переменных в определённой области видимости перед выполнением регулярного выражения.
Если шаблон не содержит специальной управляющей вербы обратной подстановки, которая допускает аргумент, то $REGERROR и $REGMARK не изменяются вообще.
- Глаголы
-
-
(*PRUNE)(*PRUNE:NAME) -
Этот шаблон нулевой ширины обрезает дерево отката в текущей точке при обратном отката при ошибке. Рассмотрим шаблон
/A (*PRUNE) B/, где A и B — сложные шаблоны. До тех пор, пока не будет достигнут глагол(*PRUNE), A может осуществлять обратный откат по мере необходимости для соответствия. Как только он будет достигнут, соответствие продолжается в B, которое также может осуществлять обратный откат по мере необходимости; однако, если B не соответствует, то дальнейший обратный откат не будет происходить, и шаблон будет полностью неудачным в текущей стартовой позиции.Следующий пример подсчитывает все возможные совпадающие строки в шаблоне (без фактического соответствия ни одной из них).
'aaab' =~ /a+b?(?{print "$&\n"; $count++})(*FAIL)/; print "Count=$count\n";что даёт:
aaab aaa aa a aab aa a ab a Count=9Если мы добавим
(*PRUNE)перед подсчётом, как в следующем примере'aaab' =~ /a+b?(*PRUNE)(?{print "$&\n"; $count++})(*FAIL)/; print "Count=$count\n";мы предотвращаем обратный откат и находим количество самой длинной соответствующей строки в каждой стартовой позиции соответствия, как в этом случае:
aaab aab ab Count=3В шаблоне может использоваться любое количество утверждений
(*PRUNE).См. также
"(?>pattern)"и позитивные квантификаторы для других способов управления обратным откатом. В некоторых случаях использование(*PRUNE)может быть заменено на(?>pattern)без функциональных различий; однако,(*PRUNE)можно использовать для обработки случаев, которые не могут быть выражены только с помощью(?>pattern). -
(*SKIP)(*SKIP:NAME) -
Этот шаблон нулевой ширины похож на
(*PRUNE), за исключением того, что при неудачном совпадении он также указывает, что любая строка, которая соответствовала перед выполнением шаблона(*SKIP), не может быть частью любого соответствия этого шаблона. Это эффективно означает, что движок регулярных выражений «пропускает» вперёд до этой позиции при неудачном совпадении и пытается снова найти соответствие (предполагая, что есть достаточно места для соответствия).Имя шаблона
(*SKIP:NAME)имеет особое значение. Если во время соответствия был встречен(*MARK:NAME), тогда в качестве «точки пропуска» используется эта позиция. Если(*MARK)с таким именем не был встречен, то оператор(*SKIP)не оказывает никакого эффекта. При использовании без имени «точка пропуска» находится в месте, где находилась точка совпадения при выполнении шаблона(*SKIP).Сравните следующее с примерами в
(*PRUNE); обратите внимание, что строка вдвое длиннее:'aaabaaab' =~ /a+b?(*SKIP)(?{print "$&\n"; $count++})(*FAIL)/; print "Count=$count\n";выводит
aaab aaab Count=2После того, как 'aaab' в начале строки совпало, и был выполнен
(*SKIP), следующая стартовая позиция будет той, где курсор находился при выполнении(*SKIP). -
(*MARK:NAME)(*:NAME) -
Этот шаблон нулевой ширины может использоваться для маркировки точки, достигнутой в строке, когда определенная часть шаблона успешно совпала. Эту метку можно присвоить имя. Более поздний шаблон
(*SKIP)затем перейдёт вперёд к этой точке, если при обратном отката произошла ошибка. Разрешено любое количество шаблонов(*MARK:NAME), а часть NAME может дублироваться.В дополнение к взаимодействию с шаблоном
(*SKIP),(*MARK:NAME)может использоваться для «разметки» ветви шаблона, таким образом, что после совпадения программа может определить, какие ветви шаблона были задействованы в совпадении.Когда совпадение успешно, переменная
$REGMARKбудет установлена в имя последнего выполненного(*MARK:NAME), который участвовал в совпадении.Это можно использовать для определения, какая ветвь шаблона была сопоставлена, не используя отдельную группу захвата для каждой ветви, что в свою очередь может привести к повышению производительности, так как Perl не может оптимизировать
/(?:(x)|(y)|(z))/так эффективно, как что-то вроде/(?:x(*MARK:x)|y(*MARK:y)|z(*MARK:z))/.Когда совпадение не удалось, и если другой глагол не участвовал в неудачном совпадении и не предоставил собственное имя для использования, переменная
$REGERRORбудет установлена в имя последнего выполненного(*MARK:NAME).См. "(*SKIP)" для получения более подробной информации.
В качестве сокращения
(*MARK:NAME)можно записать как(*:NAME). -
(*THEN)(*THEN:NAME) -
Это аналогично оператору «группы обрезки»
::из Perl 6. Как и(*PRUNE), этот глагол всегда соответствует, и при обратном отката при ошибке он заставляет движок регулярных выражений попробовать следующую альтернативу во внутренней вложенной группе (захвата или иного), которая имеет альтернативы. Две ветви(?(condition)yes-pattern|no-pattern)не считаются альтернативой, с точки зрения(*THEN).Его имя происходит из наблюдения, что этот оператор в сочетании с оператором альтернатив (
"|") может использоваться для создания того, что по сути является блоком if/then/else на основе шаблонов:( COND (*THEN) FOO | COND2 (*THEN) BAR | COND3 (*THEN) BAZ )Обратите внимание, что если этот оператор используется и НЕ внутри альтернативы, то он действует точно так же, как оператор
(*PRUNE)./ A (*PRUNE) B /равносильно
/ A (*THEN) B /но
/ ( A (*THEN) B | C ) /не равносильно
/ ( A (*PRUNE) B | C ) /так как после совпадения с A, но неудачи с B, глагол
(*THEN)осуществит обратный откат и попробует C; но глагол(*PRUNE)просто потерпит неудачу. -
(*COMMIT)(*COMMIT:args) -
Это «шаблон подтверждения» Perl 6
<commit>или:::. Это шаблон нулевой ширины, похожий на(*SKIP), за исключением того, что при обратном отката при ошибке он приводит к безусловной ошибке совпадения. Больше попыток найти корректное совпадение, смещая указатель начала, предприниматься не будет. Например,'aaabaaab' =~ /a+b?(*COMMIT)(?{print "$&\n"; $count++})(*FAIL)/; print "Count=$count\n";выводит
aaab Count=1Другими словами, после того, как
(*COMMIT)был введён, и если шаблон не соответствует, движок регулярных выражений не будет пытаться найти соответствие в остальной части строки. -
(*FAIL)(*F)(*FAIL:arg) -
Этот шаблон ничего не соответствует и всегда терпит неудачу. Он может использоваться для принудительного отката движка. Он эквивалентен
(?!), но легче читается. Фактически,(?!)оптимизируется в(*FAIL)внутри. Вы можете указать аргумент, так что если совпадение потерпит неудачу из-за этой директивыFAIL, то аргумент можно получить из$REGERROR.Он, вероятно, полезен только в сочетании с
(?{})или(??{}). -
(*ACCEPT)(*ACCEPT:arg) -
Этот шаблон ничего не соответствует и вызывает завершение успешного соответствия в точке, в которой был встречен шаблон
(*ACCEPT), независимо от того, есть ли ещё что-то для соответствия в строке. В случае вложенного шаблона, такого как рекурсия, или в подшаблоне, динамически сгенерированном с помощью(??{}), завершается только самый внутренний шаблон.Если
(*ACCEPT)находится внутри групп захвата, то группы отмечаются как завершённые в точке, в которой был встречен(*ACCEPT). Например:'AB' =~ /(A (A|B(*ACCEPT)|C) D)(E)/x;будет соответствовать, и
$1будетAB, а$2будет"B",$3не будет установлено. Если другая ветвь в вложенных скобках была сопоставлена, например, в строке 'ACDE', то"D"и"E"должны были быть сопоставлены также.Вы можете указать аргумент, который будет доступен в переменной
$REGMARKпосле завершения совпадения.
-
Предупреждение о \1 вместо $1
Некоторые люди привыкли писать вещи вроде:
$pattern =~ s/(\W)/\\\1/g; Это унаследовано (для \1 до \9) для правой части замены, чтобы не шокировать «зависимых от sed», но это плохая привычка. Это потому, что в PerlThink правая часть s/// — это строка в двойных кавычках. \1 в обычной строке в двойных кавычках означает управляющий символ A. Обычное unix-значение \1 подправлено для s///. Однако, если вы привыкнете к этому, вы столкнётесь с проблемами, если добавите модификатор /e.
s/(\d+)/ \1 + 1 /eg; # causes warning under -w Или если вы попытаетесь сделать
s/(\d+)/\1000/; Вы не можете разрешить неоднозначность, сказав \{1}000, в то время как вы можете исправить это с помощью ${1}000. Операция интерполяции не следует путать с операцией соответствия обратной ссылки. Конечно, они означают две разные вещи в левой части s///.
Повторные шаблоны, соответствующие подстроке нулевой длины
ВНИМАНИЕ: Следующий материал сложный (и прозаичный). Этот раздел требует переработки.
Регулярные выражения предоставляют лаконичный и мощный язык программирования. Как и большинство других инструментов, с мощью приходит и способность наносить вред.
Распространённое злоупотребление этой мощью происходит из-за способности создавать бесконечные циклы с помощью регулярных выражений, с чем-то таким безобидным, как:
'foo' =~ m{ ( o? )* }x; o? соответствует в начале «foo», и так как позиция в строке не смещается при совпадении, o? будет соответствовать снова и снова из-за квантификатора "*". Ещё один распространённый способ создания подобного цикла — использование циклического модификатора /g:
@matches = ( 'foo' =~ m{ o? }xg ); или
print "match: <$&>\n" while 'foo' =~ m{ o? }xg; или цикл, подразумеваемый split().
Однако, большой опыт показал, что многие задачи программирования могут быть значительно упрощены с использованием повторяющихся подвыражений, которые могут соответствовать подстрокам нулевой длины. Вот простой пример:
@chars = split //, $string; # // is not magic in split
($whitewashed = $string) =~ s/()/ /g; # parens avoid magic s// / Таким образом, Perl позволяет такие конструкции, принудительно прерывая бесконечный цикл. Правила для этого отличаются для циклов нижнего уровня, заданных жадными квантификаторами *+{}, и для циклов высшего уровня, таких как модификатор /g или оператор split().
Циклы нижнего уровня прерываются (то есть цикл прерывается), когда Perl обнаруживает, что повторяющееся выражение соответствовало подстроке нулевой длины. Таким образом
m{ (?: NON_ZERO_LENGTH | ZERO_LENGTH )* }x; становится эквивалентным
m{ (?: NON_ZERO_LENGTH )* (?: ZERO_LENGTH )? }x; Например, эта программа
#!perl -l
"aaaaab" =~ /
(?:
a # non-zero
| # or
(?{print "hello"}) # print hello whenever this
# branch is tried
(?=(b)) # zero-width assertion
)* # any number of times
/x;
print $&;
print $1; выводит
hello
aaaaa
b Обратите внимание, что «hello» выводится только один раз, так как при обнаружении Perl шестой итерации внешнего цикла (?:)*, совпавшей с строкой нулевой длины, он останавливает "*".
Циклы более высокого уровня сохраняют дополнительное состояние между итерациями: была ли последняя совпавшая строка нулевой длины. Чтобы прервать цикл, следующей совпавшей строке после совпадения нулевой длины запрещается иметь длину ноль. Это ограничение взаимодействует с возвратом назад (см. "Возврат назад"), поэтому выбирается второе по лучшей совпадение, если лучшее совпадение имеет нулевую длину.
Например:
$_ = 'bar';
s/\w??/<$&>/g; приводит к <><b><><a><><r><>. В каждой позиции строки лучшим совпадением, данным ?? (нежадным), является совпадение нулевой длины, а второе по лучшей совпадение — то, которое найдено \w. Таким образом, совпадения нулевой длины чередуются с совпадениями длиной в один символ.
Аналогично, для повторяющихся m/()/g вторым лучшим совпадением является совпадение в позиции на один шаг дальше в строке.
Дополнительное состояние совпадения с нулевой длиной ассоциируется с совпавшей строкой и сбрасывается при каждом присваивании pos(). Совпадения нулевой длины в конце предыдущего совпадения игнорируются во время split.
Комбинирование элементов выражений регулярных
Каждый из описанных ранее элементарных фрагментов выражений регулярных (таких как ab или \Z ) может соответствовать максимум одной подстроке в данной позиции входной строки. Однако в типичном выражении регулярном эти элементарные фрагменты комбинируются в более сложные шаблоны с помощью операторов комбинирования ST, S|T, S* и т. д. (в этих примерах "S" и "T" — подвыражения регулярные).
Такие комбинации могут включать альтернативы, что приводит к проблеме выбора: если мы применяем выражение регулярное a|ab к "abc" , будет ли это соответствовать подстроке "a" или "ab"? Один способ описать, какая подстрока на самом деле соответствует, — это понятие возврата назад (см. "Возврат назад"). Однако это описание слишком низкого уровня и заставляет вас думать в терминах конкретной реализации.
Другое описание начинается с понятий «лучше»/«хуже». Все подстроки, которые могут соответствовать данному выражению регулярному, могут быть отсортированы от «лучшего» совпадения к «худшему» совпадению, и выбирается «лучшее» совпадение. Это заменяет вопрос «что выбрано?» вопросом «какие совпадения лучше, а какие хуже?».
Опять же, для элементарных фрагментов такого вопроса нет, так как максимум одно совпадение в данной позиции возможно. В этом разделе описывается понятие «лучше»/«хуже» для операторов комбинирования. В описании ниже "S" и "T" — выражения регулярные.
ST-
Рассмотрим два возможных совпадения,
ABиA'B',"A"иA'— подстроки, которые могут соответствовать"S","B"иB'— подстроки, которые могут соответствовать"T".Если
"A"— лучшее совпадение для"S", чемA', тоAB— лучшее совпадение, чемA'B'.Если
"A"иA'совпадают:AB— лучшее совпадение, чемAB', если"B"— лучшее совпадение для"T", чемB'. -
S|T -
Когда
"S"может соответствовать, это лучшее совпадение, чем когда может соответствовать только"T".Порядок двух совпадений для
"S"такой же, как и для"S". Аналогично для двух совпадений для"T". -
S{REPEAT_COUNT} -
Совпадает как
SSS...S(повторяется столько раз, сколько необходимо). -
S{min,max} -
Совпадает как
S{max}|S{max-1}|...|S{min+1}|S{min}. -
S{min,max}? -
Совпадает как
S{min}|S{min+1}|...|S{max-1}|S{max}. -
S?,S*,S+ -
То же самое, что и
S{0,1},S{0,BIG_NUMBER},S{1,BIG_NUMBER}соответственно. -
S??,S*?,S+? -
То же самое, что и
S{0,1}?,S{0,BIG_NUMBER}?,S{1,BIG_NUMBER}?соответственно. -
(?>S) -
Совпадает с лучшим совпадением для
"S"и только с ним. -
(?=S),(?<=S) -
Рассматривается только лучшее совпадение для
"S". (Это важно только если"S"имеет группирующие скобки и где-то в выражении регулярном используются обратные ссылки.) -
(?!S),(?<!S) -
Для этого оператора группирования нет необходимости описывать порядок, так как важно только то, может ли
"S"соответствовать или нет. -
(??{ EXPR }),(?PARNO) -
Порядок такой же, как для выражения регулярного, которое является результатом EXPR, или шаблона, содержащегося в группе захвата PARNO.
-
(?(condition)yes-pattern|no-pattern) -
Напомним, что какой из
yes-patternилиno-patternфактически соответствует, уже определено. Порядок совпадений такой же, как и для выбранного подвыражения.
Вышеприведенные рецепты описывают порядок совпадений в данной позиции. Для понимания того, как определяется совпадение для всего выражения регулярного, требуется еще одно правило: совпадение в более ранней позиции всегда лучше, чем совпадение в более поздней позиции.
Создание пользовательских движков выражений регулярных
Начиная с Perl 5.10.0, можно создавать пользовательские движки выражений регулярных. Это не для слабонервных, так как они должны быть подключены на уровне C. См. perlreapi для получения дополнительной информации.
В качестве альтернативы перегруженные константы (см. overload) предоставляют простой способ расширить функциональность движка выражений регулярных, заменив один шаблон другим.
Предположим, что мы хотим включить новую последовательность escape \Y| выражения регулярного, которая соответствует границе между пробелами и не-пробелами. Обратите внимание, что (?=\S)(?<!\S)|(?!\S)(?<=\S) соответствует точно в этих позициях, поэтому мы хотим заменить каждое \Y| на более сложную версию. Мы можем создать модуль customre для этого:
package customre;
use overload;
sub import {
shift;
die "No argument to customre::import allowed" if @_;
overload::constant 'qr' => \&convert;
}
sub invalid { die "/$_[0]/: invalid escape '\\$_[1]'"}
# We must also take care of not escaping the legitimate \\Y|
# sequence, hence the presence of '\\' in the conversion rules.
my %rules = ( '\\' => '\\\\',
'Y|' => qr/(?=\S)(?<!\S)|(?!\S)(?<=\S)/ );
sub convert {
my $re = shift;
$re =~ s{
\\ ( \\ | Y . )
}
{ $rules{$1} or invalid($re,$1) }sgex;
return $re;
} Теперь use customre включает новую последовательность escape в константных выражениях регулярных, т.е., тех, без каких-либо переменных вставляемых во время выполнения. Как документировано в overload, эта конвертация будет работать только над буквальными частями выражений регулярных. Для \Y|$re\Y| переменная часть этого выражения регулярного должна быть преобразована явно (но только если специальное значение \Y| должно быть включено внутри $re):
use customre;
$re = <>;
chomp $re;
$re = customre::convert $re;
/\Y|$re\Y|/; Частота выполнения встраиваемого кода
Точные правила о том, как часто выполняются (??{}) и (?{}) в шаблоне, не определены. В случае успешного совпадения можно предположить, что они работают так, как нужно, и будут выполнены слева направо в нужное количество раз в пути принятия шаблона, как и любой другой меташаблон. То, как пути не принятия и ошибки совпадения влияют на количество раз выполнения шаблона, не определено специально и может меняться в зависимости от применяемых оптимизаций к шаблону и, вероятно, будет меняться от версии к версии.
Например, в
"aaabcdeeeee"=~/a(?{print "a"})b(?{print "b"})cde/; точное количество раз, когда выводится «a» или «b», не определено при ошибке, но можно предположить, что они будут выведены по крайней мере один раз во время успешного совпадения, дополнительно можно предположить, что если выводится «b», то ему будет предшествовать по крайней мере одно «a».
В случае разветвленных конструкций, подобных следующим:
/a(b|(?{ print "a" }))c(?{ print "c" })/; можно предположить, что вход «ac» выведет «ac», а «abc» выведет только «c».
Когда встраиваемый код квантифицирован, успешные совпадения вызовут код один раз для каждой совпавшей итерации квантификатора. Например:
"good" =~ /g(?:o(?{print "o"}))*d/; выведет «o» дважды.
Поддержка PCRE/Python
Начиная с Perl 5.10.0, Perl поддерживает несколько расширений синтаксиса регулярных выражений, специфичных для Python/PCRE. Хотя программистам Perl рекомендуется использовать специфичный для Perl синтаксис, следующие также принимаются:
-
(?P<NAME>pattern) -
Определяет именованную группу захвата. Эквивалентно
(?<NAME>pattern). -
(?P=NAME) -
Обратная ссылка на именованную группу захвата. Эквивалентно
\g{NAME}. -
(?P>NAME) -
Вызов подпрограммы к именованной группе захвата. Эквивалентно
(?&NAME).
ОШИБКИ
Существует ряд проблем, связанных с регистронезависимым соответствием в правилах Юникод. См. "i" в "Модификаторы" выше.
Этот документ варьируется от труднопонимаемого до полностью и совершенно непрозрачного. Бродящий по тексту, наполненный жаргоном, слог трудно понять в нескольких местах.
Этот документ требует переработки, которая отделяет учебный контент от справочного контента.
См. также
Синтаксис шаблонов, используемых в Perl для сопоставления с образцом, эволюционировал из шаблонов, предоставленных в Bell Labs Research Unix 8-й версии (Версия 8) в процедурах регулярных выражений. (Код фактически (далекое) почерпнут из свободно распространяемой переработки Генри Спенсера этих процедур V8.)
"Операторы цитирования регулярных выражений" в perlop.
"Подробности разбора цитируемых конструкций" в perlop.
Мастерство регулярных выражений Джеффри Фридла, опубликованное издательством O'Reilly и Associates.
© 1993–2020 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.28.3/perlre