Регулярные выражения представляют собой образцы для поиска заданных комбинаций символов в текстовых строках и замены их на другие комбинации символов (эти операции называются соответственно сопоставление с образцом и подстановка). Регулярное выражение имеет вид:
/pattern/modifiers
Здесь pattern — это строка, задающая регулярное выражение, а modifiers — необязательные однобуквенные модификаторы, уточняющие правила использования этого регулярного выражения.
Регулярное выражение может состоять из обычных символов; в этом случае оно будет соответствовать заданной комбинации символов в строке. Например, выражение /кат/ соответствует выделенным подстрокам в следующих строках: "каток", "закат", "укатить". Однако, подлинную силу регулярным выражениям придает возможность использования в них специальных метасимволов.
Символ | Описание |
---|---|
\ | Для символов, которые обычно трактуются буквально, означает, что следующий символ является метасимволом. Например, /n/ соответствует букве n, а /\n/ соответствует символу перевода строки. Для метасимволов означает, что символ должен пониматься буквально. Например, /^/ означает начало строки, а /\^/ соответствует просто символу ^. /\\/ соответствует обратной косой черте \. |
^ | Соответствует началу строки (ср. модификатор m ). |
$ | Соответствует концу строки (ср. модификатор m ). |
. | Соответствует любому символу, кроме разрыва строки (ср. модификатор s ). |
* | Соответствует повторению предыдущего символа нуль или более раз. |
+ | Соответствует повторению предыдущего символа один или более раз. |
? | Соответствует повторению предыдущего символа нуль или один раз. |
(pattern ) | Соответствует строке pattern и запоминает найденное соответствие. |
x | y | Соответствует x или y . |
{ n } | n — неотрицательное число. Соответствует ровно n вхождениям предыдущего символа. |
{ n ,} | n — неотрицательное число. Соответствует n или более вхождениям предыдущего символа. /x{1,}/ эквивалентно /x+/. /x{0,}/ эквивалентно /x*/. |
{ n , m } | n и m — неотрицательные числа. Соответствует не менее чем n и не более чем m вхождениям предыдущего символа. /x{0,1}/ эквивалентно /x?/. |
[ xyz ] | Соответствует любому символу из заключенных в квадратные скобки. |
[^ xyz ] | Соответствует любому символу, кроме заключенных в квадратные скобки. |
[ a - z ] | Соответствует любому символу в указанном диапазоне. |
[^ a - z ] | Соответствует любому символу, кроме лежащих в указанном диапазоне. |
\a | Соответствует символу звонок (BEL). |
\A | Соответствует только началу строки, даже с модификатором m . |
\b | Соответствует границе слова, т. е. позиции между \w и \W в любом порядке. |
\B | Соответствует любой позиции, кроме границы слова. |
\с X | Соответствует символу Ctrl+X. Например, /\cI/ эквивалентно /\t/. |
\C | Соответствует одному байту, даже при директиве use utf8 . |
\d | Соответствует цифре. Эквивалентно . |
\D | Соответствует нецифровому символу. Эквивалентно [^0-9]. |
\e | Соответствует символу escape (ESC). |
\E | Конец преобразований \L , \Q , \U . |
\f | Соответствует символу перевода формата (FF). |
\G | Соответствует позиции в строке, равной pos() . |
\l | Преобразует следующий символ в нижний регистр. |
\L | Преобразует символы в нижний регистр до \E . |
\n | Соответствует разрыву строк. |
\p property | Соответствует символам Unicode, обладающим свойством property . Если property \p{ property } . |
\P property | Соответствует символам Unicode, не обладающим свойством property . Если property задается несколькими символами, используйте синтаксис \P{ property } . |
\Q | Добавляет символ "\\" перед метасимволами до \E . |
\r | Соответствует символу возврата каретки (CR). |
\s | Соответствует символу пробела. Эквивалентно /[ \f\n\r\t]/. |
\S | Соответствует любому непробельному символу. Эквивалентно /[^ \f\n\r\t]/. |
\t | Соответствует символу табуляции (HT). |
\u | Преобразует следующий символ в верхний регистр. |
\U | Преобразует символы в верхний регистр до \E . |
\w | Соответствует латинской букве, цифре или подчеркиванию. Эквивалентно / /. |
\W | Соответствует любому символу, кроме латинской буквы, цифры или подчеркивания. Эквивалентно /[^A-Za-z0-9_] /. |
\X | Соответствует последовательности символов Unicode из основного символа и набора диакритических значков. Эквивалентно выражению /C<(?:\PM\pM*)>/. |
\z | Соответствует только концу строки, даже с модификатором m . |
\Z | Соответствует только концу строки или разрыву строк в конце строки, даже с модификатором m . |
\ n | n — положительное число. Соответствует n -ной запомненной подстроке. Если левых скобок до этого символа меньше, чем n , и n > 9, то эквивалентно \0n . |
\0 n | n — восьмеричное число, не большее 377. Соответствует символу с восьмеричным кодом n . Например, /\011/ эквивалентно /\t/. |
\x n | n — шестнадцатеричное число, состоящее из двух цифр. Соответствует символу с шестнадцатеричным кодом n . Например, /\x31/ эквивалентно /1/. |
\x{ n } | n — шестнадцатеричное число, состоящее из четырех цифр. Соответствует символу Unicode с шестнадцатеричным кодом n . Например, /\x{2663}/ эквивалентно /♣/. |
Разные операции с регулярными выражениями используют разные модификаторы для уточнения выполняемой операции. Однако, четыре модификатора имеют общее назначение.
Мы можем использовать в регулярных выражениях синтаксис
[:class:]
где class задает название класса символов POSIX, т. е. мобильного стандарта на язык C. При использовании директивы use utf8 вместо классов POSIX можно использовать классы символов Unicode в конструкции
\p{class}
В следующей таблице сведены все классы символов POSIX, соответствующие классы символов Unicode и метасимволы, если они есть.
POSIX | Unicode | Метасимвол | Описание |
---|---|---|---|
alpha | IsAlpha | Буквы | |
alnum | IsAlnum | Буквы и цифры | |
ascii | IsAscii | Символы ASCII | |
cntrl | IsCntrl | Управляющие символы | |
digit | IsDigit | \d | Цифры |
graph | IsGraph | Буквы, цифры и знаки пунктуации | |
lower | IsLower | Строчные буквы | |
IsPrint | Буквы, цифры, знаки пунктуации и пробел | ||
punct | IsPunct | Знаки пунктуации | |
space | IsSpace | \s | Символы пробела |
upper | IsUpper | Прописные буквы | |
word | IsWord | \w | Буквы, цифры и подчеркивание |
xdigit | IsXDigit | Шестнадцатеричные цифры |
Например, десятичное число можно задать любым из следующих трех способов:
/\d+/
/[:digit:]+/
/\p{IsDigit}+/ # use utf8
Для указания того, что символ не принадлежит к заданному классу, используются конструкции
[:^class:]
\P{class}
Например, следующие выражения имеют одинаковый смысл:
[:^digit:] \D \P{IsDigit}
[:^space:] \S \P{IsSpace}
[:^word:] \W \P{IsWord}
Использование круглых скобок в регулярном выражении приводит к тому, что подстрока, соответствующая образцу в скобках, запоминается в специальном буфере. Внутри функции, которая будет выполнять операцию со строкой при помощи вышеприведенного условия, совпадение будет запоминаться в специальных переменных, в PHP к ней можно обращаться через \1 в Perl - $1. В одном условии поиска может быть несколько инструкций запоминания: ({5})({4}) - проверит строку на совпадение с условием, в случае удачного совпадения, запомнит пять букв в \1 ($1), четыре цифры в \2 ($2). Если обратиться к переменной \0, то окажется, что в ней хранится вся совпавшая строка, которая была описана условием.
В РНР существует пять функций поиска по шаблону с использованием Perl-совместимых регулярных выражений:
Язык, созданный первоначально с главной целью облегчить обработку большого количества отчетов, просто обязан располагать развитыми средствами для работы с текстом. Напомним, что в среде UNIX, из которой вышел язык Perl, средства для обработки текстовых строк имеются в различных утилитах: sed, awk, grep, cut, а командный интерпретатор shell, также обладающий некоторыми средствами для обработки строк, позволяет организовать совместную работу этих утилит, передавая выход одной программы на вход другой через механизм, называемый конвейером. Такой подход требует написания достаточно изощренных сценариев на языке shell в сочетании с обращением к внутренним командам утилит обработки текста sed или awk. Язык Perl, являясь средством создания программ-сценариев, в то же время один обладает всеми возможностями перечисленных утилит и даже их превосходит. Типичная задача, возникающая при обработке текстового файла, заключается в том, чтобы найти в нем фрагмент, удовлетворяющий заданным условиям, и выполнить над найденным фрагментом некоторую операцию: удалить, заменить на другой фрагмент, извлечь для дальнейшего использования и т. д. Условия поиска можно достаточно просто выразить словами. Например: найти строку, содержащую слово Perl. Или: найти все фрагменты, находящиеся в конце строки и содержащие две цифры, за которыми следует произвольное количество прописных букв. Для формализованной записи подобных условий используются регулярные выражения, позволяющие описать образец, или шаблон поиска при помощи специальных правил. Манипуляции с регулярными выражениями осуществляются при помощи соответствующих операций, которые мы также рассмотрим в этой главе.
ПРИМЕЧАНИЕ Последовательность \А эквивалентна метасимволу ^ в начале регулярного выражения, а последовательность \Z - метасимволу $ в конце регулярного выражения, за исключением одного случая. Назовем строку, содержащую внутри себя символы новой строки (ASCII 10), мультистрокой. Фактически мультистрока состоит из отдельных строк, разделенных ограничителями - символами новой строки. При выводе мультистрока отображается в виде нескольких строк. Если к мультистроке применяется операция поиска или замены с опцией /m, то последовательности \А и \Z обозначают соответственно начало и конец всей мультистроки, а метасимволам ^ и $ соответствуют еще и границы внутренних строк, образующих мультистроку.
Метасимвол | Интерпретация |
---|---|
\ | Отменяет (экранирует) специальное значение следующего за ним метасимвола |
. | Любой одиночный символ, кроме символа новой строки. Любой одиночный символ, включая символ новой строки, если в операции сопоставления с образцом задан флаг s |
^ | Обозначает начало строки, если является первым символом образца |
$ | Обозначает коней строки, если является последним символом образца |
| | Разделяет альтернативные варианты |
[...] | Любой одиночный символ из числа перечисленных в квадратных скобках. Пара символов, разделенных знаком минус, задает диапазон символов. Например, задает все прописные и строчные буквы английского алфавита. Если первым символом в скобках является символ ^, вся конструкция обозначает любой символ, не входящий в число перечисленных в скобках. Внутри скобок символы. * [ и \ теряют свое специальное значение. |
(...) | Группирование элементов образца в один элемент |
* | Нуль и более повторений регулярного выражения, стоящего непосредственно перед * |
+ | Одно или более повторений регулярного выражения, стоящего Непосредственно перед + |
? | Одно или ни одного повторения регулярного выражения, стоящего непосредственно перед? |
{n, m} | Минимальное n и максимальное m число повторений регулярного выражения, стоящего перед {n, m}. Конструкция {n} означает ровно n повторений, {n,} - минимум n повторений |
Метапоследовательность | Значение |
---|---|
\0nn | Символ, восьмеричный код которого равен nn |
\а | При выводе производит звуковой сигнал |
\А | Обозначает начало строки |
\b | Обозначает границы слова. Под словом понимается последовательность символов из класса \w. Граница слова определяется как точка между символами из класса \w и символами из класса \W |
\B | Обозначает не-границы слова |
\cn | Управляющий символ, который генерируется при нажатии комбинации клавиш Ctrl+n |
\d | Любой цифровой символ, то же, что и |
\D | Любой нецифровой символ, то же, что и [^0-9] |
\е | Символ Esc, ASCII 27 |
\E | Ограничитель последовательностей \L, \U, \Q |
\f | Символ перевода страницы, ASCII 12 |
\G | Обозначает точку, в которой закончился предыдущий поиск m//g |
\l | Преобразует следующий символ регулярного выражения в нижний регистр |
\L | Преобразует все последующие символы в регулярном выражении в нижний регистр до тех пор, пока не встретится последовательность \Е |
\n | Символ новой строки, ASCII 10 |
\Q | Эквивалентно экранированию всех последующих метасимволов в регулярном выражении при помощи символа \ до тех пор, пока не встретится последовательность \Е |
\r | Символ «возврат каретки», ASCII 13 |
\s | Класс пробельных символов: пробел (space), символ табуляции (tab), возврат каретки (carriage return), символ перевода строки (line feed) и символ перевода страницы (form feed); эквивалентно [\t,\r,\n,\f] |
\S | Класс непробельных символов |
\t | Символ табуляции, ASCII 9 |
\u | Преобразует следующий символ в верхний регистр |
\U | Преобразует все последующие символы в регулярном выражении в верхний регистр до тех пор, пока не встретится последовательность \Е |
\v | Символ вертикальной табуляции, ASCII 11 |
\w | Любая буква, цифра или символ подчеркивания |
\W | Любой символ, не являющийся буквой, цифрой или символом подчеркивания |
\xnn | Символ, шестнадцатеричный код которого равен nn |
\Z | Обозначает конец строки |
$text = "Here is the text."
$text =~ tr[\000-\040\177\377][\040]s;
print $text;
Here is the text.
$text = "Here is the texxxxxxt.";
$text =~ tr/a-zA-Z/s;
print $text;
Here is the text.
$xcount=($text =~ tr/A-Za-z//c);
$text =- tr{\200-\377}{\000-\l77};
$text =~ tr[\000-\037\177]d;
$text =~ tr/\021-\176/ /cs;
Чтобы выделить слово, можно использовать метасимвол \S соответствующий символам, отличным от "пробельных":
$text = "Now is the time.";
$text =- /(\S+)/;
print ;
Now
Однако метасимвол \S соответствует также и символам, обычно не используемым для идентификаторов. Чтобы отобрать слова, составленные из латинских букв, цифр и символов подчеркивания, нужно использовать метасимвол \w:
$text = "Now is the time.";
$text =~ /(\w+)/;
print ;
Now
Если требуется включить в поиск только латинские буквы, надо использовать класс символов:
$text = "Now is the time.";
$text =~ /(+)/;
print ;
Now
Более безопасный метод состоит в том, чтобы включить в шаблон мнимые символы границы слова:
$text = "How is the time.";
$text=~/\b(+)\b/;
print ;
Now
Началу строки соответствует метасимвол (мнимый символ) ^ . Чтобы шаблон к началу строки, надо задать этот символ в начале регулярного выражения. Например, вот так можно проверить, что текст не начинается с точки:
$line = ".Hello!";
if($line=~m/^\./){
print "Shouldn"t start a sentence with a period!\n";
}
Shouldn"t start a sentence with a period!
Чтобы точка, указанная в шаблоне, не интерпретировалась как метасимвол перед ней пришлось поставить обратную косую черту.
Привязка к концу строки
Чтобы привязать шаблон к концу строки, используется метасимвол (мнимый символ) $ . В нашем примере мы используем привязку шаблона к началу и к концу строки, чтобы убедиться, что пользователь ввел только слово "exit":
While(<>){
if(m/"exlt$/) {exit;}
}
Поиск чисел
$test = "Hello!";
if($text =~ /\D/){
print "It is not a number.\n";
}
It is not a number.
To же самое можно проделать, использовав метасимвол \d:
$text = "333";
if($text =~ /^\d+$/){
print "It is a number.\n";
}
It is a number.
Вы можете потребовать, чтобы число соответствовало привычному формату. То есть число может содержать десятичную точку, перед которой стоит по краййей мере одна цифра и, возможно, какие-то цифры после нее:
$text= "3,1415926";
if($text =~ /^(\d+\.\d*|\d+)$/){
print "It is a number.\n";
}
It is a number.
Кроме того, при проверке можно учитывать тот факт, что перед числом может стоять как плюс, так и минус (или пустое место):
$text = "-2.7182";
if ($text =~ /^([+-]*\d+)(\.\d*|)$/) {
print "It is a number.\n";
Поскольку плюс является метасимволом, его надо защищать обратной косой чертой. Однако внутри квадратных скобок, то есть класса символов, он не может быть квантификаторам. Знак "минус" внутри класса символов обычно играет роль оператора диапазона и поэтому должен защищаться обратной косой чертой. Однако в начале или в конце шаблона он никак не может обозначать диапазон, и поэтому обратная косая черта необязательна. Наконец, более строгая проверка, требует, чтобы знак, если он присутствует, был только один:
$text = "+0.142857142857142857";
if ($text =~ /^(+|-|)\d+(\.\d*\)$/) {
print "It is a number.\n";
}
It is a number.
Альтернативные шаблоны, если они присутствуют, проверяются слева направо. Перебор вариантов обрывается, как только найдено соответствие между текстом и шаблоном. Поэтому, например, порядок альтернатив в шаблоне (\.\d*|) мог бы стать критичным, если бы не привязка к концу строки. Наконец, вот как можно произвести проверку того, что текст является шестна-дцатеричным числом без знака и остальных атрибутов:
$text = "1AO";
unless (ftext =~ m/^+$/) {
print "It is not a hex number, \n";
}
С помощью метасимвола \w можно проверить, состоит ли текст только из букв, цифр и символов подчеркивания (это те символы, которые perl называет словесными (word characters)):
$text="abc";
if($text=~/^\w+$/){
print "Only word characters found. \n";
}
Only word characters found.
Однако, если вы хотите убедиться, что текст содержит латинские буквы и несодержит цифр или символов подчеркивания, придется использовать другой шаблон:
$text = "аbс";
if($text=~ /^+$/) {
print "Only letter characters found.\n";
}
Qnly letter characters found.
Наконец, для проверки, что текст является идентификатором, то есть начинаетcя с буквы и содержит буквы, цифры и символы подчеркивания, можно испольpовать команду:
$text = "X125c";
if($text=~ /^\w+$/) {
print "This is identifier.\n";
}
This is identifier.
Для поиска нескольких вхождений шаблона можно использовать модификатор g . Следующий пример, который мы уже видели ранее, использует команду m/.../ с модификатором g для поиска всех входжений буквы x в тексте:
$text="Here is texxxxxt";
while($text=~m/x/g) {
print "Found another x.\n";
}
Found another x.
Found another x.
Found another x.
Found another x.
Found another x.
Модификатор g делает поиск глобальным. В данном (скалярном) контексте perl помнит, где он остановился в строке при предыдущем поиске. Следующий поиск продолжается с отложенной точки. Без модификатора g команда m/.../ будет упорно находить первое вхождение буквы х, и цикл будет продолжаться бесконечно.
В отличие от команды m/.../ команда s/.../.../ с модификатором g выполняет глобальную замену за один раз, работая так, будто внутри нее уже имеется встроенный цикл поиска, подобный приведенному выше. Следующий пример за один раз заменяет все вхождения х на z:
$text = "Here is texxxxxt.";
$text =~ s/x/z/g;
print $text;
Here is tezzzzzt.
Без модификатора g команда s/.../.../ заменит только первую букву х. Команда s/.../.../ возвращает в качестве значения число сделанных подстановок, что может оказаться полезным:
$text= "Here is texxxxxt.";
print (text =~ s/x/z/g)
5
Поиск нечувствительных к регистру совпадений
Вы можете использовать модификатор i , чтобы сделать поиск нечувствительным к разнице между заглавными и строчными буквами. В следующем примере про-грамма повторяет на экране введенный пользователем текст до тех пор, пока не будет введено Q , или q (сокращение для QUIT или quit), после чего программа прекращает работу:
While(<>) {
chomp;
unless (/^q$/i){
print
} else {
exit;
}
}
Чтобы получить найденную подстроку текста, можно использовать круглые скобки в теле шаблона. Если это более удобно, можно также использовать встроенную функцию substr. В следующем примере мы вырезаем из текстовой строки нужный нам тип изделия:
$record = "Product number:12345
Product type: printer
Product price: 5";
if($record=~/Product type:\s*(+)/i){
print "The product"s type Is^.\n";
}
product"s type is printer.
Используя для команды s/.../.../ модификатор е, вы тем самым показываете, что правый операнд (то есть подставляемый текст) - это то выражение perl, которое надо вычислить. Например, с помощью встроенной функции perl uc (uppercase) можно заменить все строчные буквы слов строки на заглавные:
$text = "Now is the time.";
$text=~ s/(\w+)/uc()/ge;
print $text;
NOW IS THE TIME.
Вместо функции uc($l) можно поместить произвольный код, включая вызовы программ.
С помощью модификатора g перебираются все вхождения заданного шаблона. Но то делать, если нужна вполне определенная точка совпадения с шаблоном, например, вторая или третья? Оператор цикла while в сочетании с круглыми cкобками, выделяющими нужный образец, поможет вам:
$text = "Name:Anne Nanie:Burkart Name:Glaire Name: Dan";
while ($text =~ /Name: \s*(\w+)/g) {
++$match;
print "Match number $match is .\n";
}
Match number 1 is Anne
Match number 2 is Burkart
Match number 3 is Claire
Match number 4 is Dan
Этот пример можно переписать, используя цикл for:
$text = "Name:Anne Name:Burkart Name:Ciaire Name:Dan";
for ($match = 0;
$text =~ /Name:\s*(\w+)/g;
print "Match number ${\match} is .\n")
{}
Match nuwber 1 Is Anne
Match number 2 is Burkart
Match number 3 is Claire
Match number 4 is Dan
Если же вам требуется определить нужное совпадение не по номеру, а по содержанию (например, по первой букве имени пользователя), то вместо счетчика $match можно анализировать содержимое переменной, обновляемой при каждом найденном совпадении. Когда требуется не найти, а заменить второе или третье вхождение текста, можно применить ту же схему, использовав в качестве тела цикла выражение perl, вызываемое для вычисления заменяющей строки:
$text = "Name:Anne Name:Burkart Name:Claire Name:Dan";
$match =0;
$text =~ s/(Name:\s*(\w+))/ # начинается код perl
if (++$match == 2) { # увеличить счетчик
"Name:John ()" # вернуть новое значение
} else { }# оставить старое значение
/gex;
print $text;
Name:Anne Name:John (Burkart) Name:ClaireName:Dan
В процессе глобального поиска при каждом найденном совпадении вычисляется выражение, указанное в качестве второго операнда. При его вычислении увеличивается значение счетчика, и в зависимости от него в качестве замены подставляется либо старое значение текста, либо новое. Модификатор х позволяет добавить в поле шаблона комментарии, делая код более прозрачным. Обратите внимание, что нам пришлось заключить весь шаблон в круглые скобки, чтобы получить значение найденного текста и подставить его на прежнее место полностью.
По умолчанию квантификаторы ведут себя как "жадные" объекты. Начиная с текущей позиции поиска, они захватывают самую длинную строку, которой может соответствовать регулярное выражение, стоящее перед квантификатором. Алгоритм перебора с возвратами, используемый perl, способен ограничивать аппетит квантификаторов, возвращаясь назад и уменьшая длину захваченной строки, если не удалось найти соответствия между текстом и шаблоном. Однако этот механизм не всегда работает так, как хотелось бы. Рассмотрим следующий пример. Мы хотим заменить текст "That is" текстом "That"s". Однако в силу "жадности" квантификатора регулярное выражение " .*is " сопоставляется фрагменту текста от начала строки и до последнего найденного "is":
$text =~ s/.*is/That"s/;
print $texts;
That"sn"t it?
Чтобы сделать квантификаторы не столь жадными, а именно заставить их захватывать минимальную строку, с которой сопоставимо регулярное выражение, после квантификатора нужно поставить вопросительный знак. Тем самым квантификаторы принимают следующий вид:
Оратите внимание, что смыслквантификатора от этого не меняется; меняется только поведение алгоритма поиска. Если в процессе сопоставления шаблона и текста прототип определяется однозначно, то алгоритм поиска с возвратами увеличит "жадность" такого квантификатора точно так же, как он ограничивает аппетит собрата. Однако если выбор неоднозначен, то результат поиска будет другим:
$text = "That is some text, isn"t it?";
$text =~ s/.*?is/That"s/;
print $texts;
That"s some text, isn"t it?
Чтобы отсечь от строки начальные "пробельные символы", можно использовать, следующую команду:
$text = " Now is the time.";
$text =~ s/^\s+//;
print $texts;
Now is the time.
Чтобы отсечь "хвостовые" пробелы, годится команда:
$text = "Now is the time. ";
$text =~ s/\s+$//;
print $texts;
Now is the time.
Чтобы отсечь и начальные, и хвостовые пробелы лучше вызвать последователно эти две команды, чем использовать шаблон, делающий отсечение ненужных пробелов за один раз. Поскольку процедура сопоставления шаблона и текста достаточно сложна, на эту простую операцию может уйти гораздо больше времеви, чем хотелось бы.
Например в тексте нужно найти текст, находящийся между открывающим и закрывающим тегом:
$text="blah-blah";
if($text=~m!<()>(.*?)/\1!ig) {
print "\n";
}
найдет все слова, стоящие между тегами и .
В регулярных выражениях пристутствует своя семантика: быстрота, торопливость и возврат. Если квантификатор * совпадает во многих случаях, то в результате быдет выведен наибольший по длинне результат. Это жадность. Быстрота: поиск старается найти как можно быстрее. "Text"=~/m*/ , по смыслу символов m нет, но в результате будет возвращено значение 0 . Т.е. формально 0 и более символов.
$test="aaooee ooaao";
$test=~s/o*/e/;
print $test;
eaaooee ooaao
потому что 1 элемент сторки - 0 и более символов.
Если добавить квантификатор g , то результат будет таким:
Eaeaeeeeee eeaeaee
т.к строка содержит 13 мест, где может встречатся o , в том числе и пустых.
Модификаторы:
при вызове use locаle учитываются локальные настройки. Модификатор /g может заполнить массив значений @nums = m/(\d+)/g; но это сработает для ненакладывающихся совпадений. Чтобы поймать совпадения нужно воспользоваться оператором?=... Если ширина = 0 , то механизм поиска остался на прежнем месте. Найденые данные остаются внутри скобок. Если есть модификатор /g , то текущая позиция остается прежней, но происходит перемещение на один символ вперед.
$numbers="123456789";
@one=$numbers=~/(\d\d\d)/g;
@two=$numbers=~/(?=(\d\d\d))/g;
print "@one \n";
print "@two \n";
Модификаторы m и s нужны для поиска последовательностей символов, содержащих перевод строки. При s точка совпадает с \n и игнорируется $* . m делает совпадающими ^ и $ до и после \n . e правая часть выполняется как программный код: perl -i -n -p -e "s/(.)/lc()/g" *.html приводит все литеры во всех файлах *.html текущей директории к нижнему регистру.
> Регулярные выражения в Perl
Регулярные выражения используются для нахождения шаблонов в строках. Например, для того, чтобы найти в телефонной книге конкретное имя, или,например, все имена, начинающиеся с буквы "a". Работа с регулярными выражениями является одной из самых мощных и полезных, и в тоже время самых сложных для понимания особенностей Perl. Надеемся, что после прочтения этой статьи вы поймете, насколько это мощный и удобный инструмент. Получив некоторый опыт вы сможете использовать эти возможности с большой пользой для себя.
Для работы с регулярными выражениями в Perl используются три оператора
- оператор сравнения (matching - m//), оператор подстановки
(substitution s///) и оператор перевода (translation - tr///).
Все три оператора используют переменную $_ по умолчанию, поэтому
дальше, пока не будут представлены операции =~ и!~, будем
пользоваться ею.
Оператор сравнения
проверяет, подходит ли проверяемое выражение под
шаблон, и возвращает значение 1, если это так, и значение 0 в
противном случае. Запись этого оператора состоит из буквы m,
разделителя (чаще всего это косая линия - /, но в принципе это может
быть почти любой символ), шаблона и еще одного разделителя (такого же,
как и первый:).
Оператор сравнения
$_ = ;
if (m/hello/) {
print "hello user\n";
}
if ($input{"siteurl"} =~ #http://#) {
print $input{"siteurl"};
}
В этом примере проверяется, есть ли в строке, полученной со
стандартного входа, слово "hello". Если это так (оператор m// вернет
значение 1), то на стандартный выход вернется фраза "hello user".
Примечание:вообще-то символ "m" является необязательным, поэтому
оператор из этого примера может выглядеть просто как /hello/.
Оператор подстановки
находит в строке все подстроки, удовлетворяющие
шаблону, и заменяет их некоторым другим значением. Запись этого
оператора состоит из буквы s, указывающей на то, что это собственно
оператор подстановки и исходного (что заменять) и подстановочного (на
что заменять) шаблонов, разделенных разделителями.
Оператор подстановки
$_ = "My name is Fred";
# oh no, my name is Jonathan!
s/Fred/Jonathan/;
В этом примере в строке $_ все слова Fred будут изменены на Jonathan.
Оператор перевода
также производит подстановку, но несколько другого
характера - он используется для замены отдельных символом некоторыми
другими (определенными) символами. Синтаксис этого оператора похож на
синтаксис оператора подстановки, с тем отличием, что во-первых он
очевидно начинается с букв tr, а между разделителями вставляются не
шаблоны, а группы символов, первая - исходные символы, вторая -
подстановочные, причем соответствующие символы должны стоять на
одинаковых позициях в своих группах - если вы хотите заменить,
например латинскую "m" на кириллическую "м", они должны стоять на
одинаковых местах: "m" - в первой группе символов, "м" - во второй.
Оператор перевода
$_ = "hi.there, my.name.is.jonathan,";
tr/.,/ !/;
В этом примере все запятые будут изменены на восклицательные знаки, а
точки - на пробелы.
Возможности каждого из этих операторов можно расширить при помощии
модификаторов. Модификаторы - это грубо говоря символы которые
дописываются к оператору (например, так - s/fred/Jonathan/i), говоря о
том, как ему нужно разбирать рабочее значение.
Модификаторы для оператора сравнения:
Модификаторы для оператора подстановки:
Модификаторы
$_ = "My name is Fred";
s/fred/Jonathan/i; # My name is Jonathan
s/jonathan/routine()/ie; # My name is
Операции =~ и!~ позволяют использовать с операторами m//, s/// и
tr/// любые переменные, а не только $_, которая используется этими
операторами по умолчанию.
Оператор =~ выполняет те же функции, что и оператор присваивания "="
(в случае использования с операторами s/// и tr///) и оператор
сравнения "eq" (при использовании с оператором m//).
Операция =~
$name = "my name is Fred";
$name =~ s/fred/Jonathan/ig;
$string = "hello world";
if ($string =~ /hello/i) {
print "helloworlded in this string.";
}
Аналогично, операция!~ используется так же как и операция "ne" (ее
написание подобно операции чисельного сравнения!=), используется
только с оператором сравнения и означает отрицание удовлетворения
шаблону.
Операция!~
$string = "good";
if ($string !~ /bad/) {
print "hey, it"s not too bad yet!";
}
И напоследок - о возможности более удобно работать с результатами
обработки регулярных выражений, а именно о хранении их в отдельных
переменных. Такими переменными являются предопределенные $&, $`, $", и
набор переменных $1, $2, ..., $9.
Переменная $&
Эта переменная предназначена для хранения фрагмента строки, который
удовлетворил шаблону, заданному регулярным выражением. Это удобно в
таких случаях, как, например, если нужно найти число в строке, но
неизвестно, что это за число. Вот как это может выглядеть:
$string = "error 404."
$string =~ m/\d+/;
Переменные $` и $ "
Эти переменные служат для хранения фрагментов, которые не
удовлетворили шаблону, а именно подстрок, которые стоят до и после
результата соответственно. Другими словами, после операции, например,
сравнения, значение исходой строки разделяется на три части - часть,
которая подошла под шаблон, и фрагменты, которые идут перед ней и
после нее. Эти части и помещаются в переменные $&, $` и $"
соответственно. (Обратите внимание на то, что в первой переменной -
обратная кавычка, а во второй - прямая). Посмотрим на предыдущий
пример.
$string = "error 404."
$string =~ m/\d+/;
$number = $&; # $number содержит "404"
$before = $`; # $before содержит "error"
$after = $"; # $after содержит "."
Эти переменные служат для хранения фрагментов строки, которые
удовлетворили соответсвующим определенным фрагментам шаблона. В
шаблоне фрагменты выделяются при помощи скобок. Каждому фрагменту
выделяется номер в том порядке, в котором они расположены, и
соответствующая переменная будет содержать его значение.
$string = "this is to be uppercased";
$string =~ s/(upper\w+)/uc($1)/;
# $string = "this is to be UPPERCASED"
$string = "15 apples, 2 foos, 3 bars";
while ($string =~ m/(\d+) (\w+)/g) {
print "$2: $1\n";
}
# Выведет apples: 15
# foos: 2
# bars: 3
Николай Матковский ,
11.05.2006.
←
В данной главе описывается синтаксис регулярных выражений. Чаще всего в Perl они используются в операторах поиска и замены таких как s// , m/ , операторах связки =~ или != и т.д. Как правило все эти операторы имеют схожие опции такие как:
Обычно все эти опции обозначают как "/x". Их можно использовать даже внутри шаблонов, используя новую конструкцию (?...)
Регулярные выражения или шаблоны (pattern) то же самое, что и regexp процедуры в Unix. Выражения и синтаксис заимствованы из свободно распространяемых процедур V8 Генри Спенсера (Henry Spencer), там же они подробно и описаны.
В шаблонах используются следующие метасимволы (символы обозначающие группы других символов) часто называемые egrep - стандартом:
Метасимволы имеют модификаторы (пишутся после метасимвола):
Во все других случаях фигурные скобки считаются обычными (регулярными) символами. Таким образом "*" эквивалентна {0,} , "+" - {1,} и "?" - {0,1}. n и m не могут быть больше 65536.
По умолчанию действие метасимволов "жадно" (greedy). Совпадение распространяется столько раз, сколько возможно, не учитывая результат действия следующих метасимволов. Если вы хотите "уменьшить их аппетит", то используйте символ "?". Это не изменяет значение метасимволов, просто уменьшает распространение. Таким образом:
Шаблоны работают так же, как и двойные кавычки, поэтому в них можно использовать `\` - символы (бэкслэш-символы):
\t | - символ табуляции |
\n | - новая строка |
\r | - перевод каретки |
\а | - перевод формата |
\v | - вертикальная табуляция |
\a | - звонок |
\e | - escape |
\033 | - восьмеричная запись символа |
\x1A | - шестнадцатеричная |
\c[ | - control символ |
\l | - нижний регистр следующего символа |
\u | - верхний регистр -//- |
\L | - все символы в нижнем регистре до \E |
\U | - в верхнем -//- |
\E | - ограничитель смены регистра |
\Q | - отмена действия как метасимвола |
Дополнительно в Perl добавлены следующие метасимволы:
Обратите внимание, что все это "один" символ. Для обозначения последовательности применяйте модификаторы. Так:
Кроме того существуют мнимые метасимволы. Обозначающие не существующие символы в месте смены значения. Такие как:Граница слова (\b) - это мнимая точка между символами \w и \W. Внутри класса символов "\b" обозначает символ backspace (стирания). Метасимволы \A и \Z - аналогичны "^" и "$", но если начало строки "^" и конец строки "$" действуют для каждой строки в многострочной строке, то \A и \Z обозначают начало и конец всей многострочной строки.
Если внутри шаблона применяется группировка (круглые скобки), то номер подстроки группы обозначается как "\цифра". Заметьте, что за шаблоном в пределах выражения или блока эти группы обозначаются как "$цифра". Кроме этого существуют дополнительные переменные:
Пример:
$s = "Один 1 два 2 и три 3"; if ($s =~ /(\d+)\D+(\d+)/) { print "$1\n"; # Результат "1" print "$2\n"; # "2" print "$+\n"; # "2" print "$&\n"; # "1 два 2" print "$`\n"; # "Один " print "$"\n"; # " и три 3" }
Perl версии 5 содержит дополнительные конструкции шаблонов:
Пример:
$s = "1+2-3*4"; if ($s =~ /(\d)(?=-)/) # Найти цифру за которой стоит "-" { print "$1\n"; # Результат "2" } else { print "ошибка поиска\n";} (?!шаблон) - "заглядывание" вперед по отрицанию.
Пример:
$s = "1+2-3*4"; if ($s =~ /(\d)(?!\+)/) # Найти цифру за которой не стоит "+" { print "$1\n"; # Результат "2" } else { print "ошибка поиска\n";}
(?ismx) - "внутренние" модификаторы. Удобно применять в шаблонах, где например нужно внутри шаблона указать модификатор.
Правила регулярного выражения. (regex)