Регулярные выражения perl онлайн. Памятка по регулярным выражениям. Регулярные выражения: Поиск с возвратом

6.4.1. Синтаксис регулярных выражений

Регулярные выражения представляют собой образцы для поиска заданных комбинаций символов в текстовых строках и замены их на другие комбинации символов (эти операции называются соответственно сопоставление с образцом и подстановка ). Регулярное выражение в языке PERL имеет вид

/pattern/modifiers

Здесь pattern — это строка, задающая регулярное выражение, а modifiers — необязательные однобуквенные , уточняющие правила использования этого регулярного выражения.

Регулярное выражение может состоять из обычных символов; в этом случае оно будет соответствовать заданной комбинации символов в строке. Например, выражение /кат/ соответствует выделенным подстрокам в следующих строках: "кат ок", "закат ", "укат ить". Однако, подлинную силу регулярным выражениям PERLа придает возможность использования в них специальных метасимволов .

Таблица 6.9. Метасимволы в регулярных выражениях
Символ Описание
\ Для символов, которые обычно трактуются буквально, означает, что следующий символ является метасимволом. Например, /n/ соответствует букве n, а /\n/ соответствует символу перевода строки.
Для метасимволов означает, что символ должен пониматься буквально. Например, /^/ означает начало строки, а /\^/ соответствует просто символу ^. /\\/ соответствует обратной косой черте \.
^ Соответствует началу строки (ср. модификатор ).
$ Соответствует концу строки (ср. модификатор ).
. Соответствует любому символу, кроме разрыва строки (ср. модификатор ).
* Соответствует повторению предыдущего символа нуль или более раз.
+ Соответствует повторению предыдущего символа один или более раз.
? Соответствует повторению предыдущего символа нуль или один раз.
(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 Соответствует только началу строки, даже с модификатором .
\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 Соответствует только концу строки, даже с модификатором .
\Z Соответствует только концу строки или разрыву строк в конце строки, даже с модификатором .
\ 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}/ эквивалентно /♣/.

6.4.2. Модификаторы

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

Игнорирует регистр символов при сопоставлении с образцом. При использовании директивы use locale приведение символов к одному регистру производится с учетом национальной настройки. Рассматривает исходную строку как буфер из нескольких строк текста, разделенных разрывами строк. Это означает, что метасимволы ^ и $ соответствуют не только началу и концу всей строки, но и началу и концу строки текста, ограниченной разрывами строк. Рассматривает исходную строку как единую строку текста, игнорируя разрывы строк. Это означает, что метасимвол . соответствует любому символу, включая разрыв строки. Разрешает использование пробелов и комментариев. Пробелы, не имеющие предшествующего символа \ и не заключенные в , игнорируются. Символ # начинает комментарий, который также игнорируется.

6.4.3. Классы символов Unicode и POSIX

Мы можем использовать в регулярных выражениях синтаксис

[:class:]

где class задает название класса символов POSIX, т. е. мобильного стандарта на язык C. При использовании директивы use utf8 вместо классов POSIX можно использовать классы символов Unicode в конструкции

\p{class}

В следующей таблице сведены все классы символов POSIX, соответствующие классы символов Unicode и метасимволы, если они есть.

Таблица 6.10. Классы символов
POSIX Unicode Метасимвол Описание
alpha IsAlpha Буквы
alnum IsAlnum Буквы и цифры
ascii IsAscii Символы ASCII
cntrl IsCntrl Управляющие символы
digit IsDigit \d Цифры
graph IsGraph Буквы, цифры и знаки пунктуации
lower IsLower Строчные буквы
print 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}

6.4.4. Запоминание подстрок

Использование круглых скобок в регулярном выражении приводит к тому, что подстрока, соответствующая образцу в скобках, запоминается в специальном буфере. Для доступа к n -ной запомненной подстроке внутри регулярного выражения используется конструкция \ n , а вне него — $ n , где n может принимать любые значения, начиная с 1. Однако, следует помнить, что PERL использует выражения \10 , \11 и т. д. как синонимы для восьмеричных кодов символов \010 , \011 и т. д. Неоднозначность здесь разрешается так. Символ \10 считается обращением к 10-й запомненной подстроке, если перед ним в регулярном выражении стоит не менее десяти левых круглых скобок; в противном случае, это символ с восьмеричным кодом 10. Метасимволы \1 , … \9 всегда считаются обращениями к запомненным подстрокам. Примеры:

If (/(.)\1/) { # ищем первый повторяющийся символ print ""$1" - первый повторяющийся символ\n"; } if (/Time: (..):(..):(..)/) { # извлекаем компоненты времени $hours = $1; $minutes = $2; $seconds = $3; }

Помимо переменных $1 , $2 , … есть еще несколько специальных переменных, в которых сохраняются результаты последней операции с регулярным выражением, а именно:

Приведем пример:

"AAA111BBB222"=~/(\d+)/; print "$`\n"; # AAA print "$&\n"; # 111 print "$"\n"; # BBB222 print "$+\n"; # 111

Все эти специальные переменные сохраняют свои значения до конца объемлющего блока или до следующего успешного сопоставления с образцом.

6.4.5. Расширенные образцы

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

(?#text ) Комментарий. Вся конструкция игнорируется. (?modifiers -modifiers ) Включает или выключает заданные . Модификаторы, стоящие до символа - , включаются, стоящие после него — выключаются. Пример:

If (/aaa/) { … } # сопоставление с учетом регистра if (/(?i)aaa/) { … } # сопоставление без учета регистра

(?:pattern ) (?modifiers -modifiers :pattern ) Позволяет группировать подвыражения регулярного выражения без запоминания найденного соответствия. Вторая форма дополнительно включает или выключает заданные . Например, выражение /ко(?:т|шка)/ — это краткая запись выражения /кот|кошка/ . (?=pattern ) Соответствие с заглядыванием вперед без запоминания найденного соответствия. Например, выражение /Windows (?=95|98|NT|2000)/ соответствует "Windows" в строке "Windows 98", но не соответствует в строке "Windows 3.1". После сопоставления поиск продолжается с позиции, следующей за найденным соответствием, без учета заглядывания вперед. (?!pattern ) Несоответствие с заглядыванием вперед без запоминания найденного соответствия. Например, выражение /Windows (?!95|98|NT|2000)/ соответствует "Windows" в строке "Windows 3.1", но не соответствует в строке "Windows 98". После сопоставления поиск продолжается с позиции, следующей за найденным соответствием, без учета заглядывания вперед. (?<=pattern ) Соответствие с заглядыванием назад без запоминания найденного соответствия. Например, выражение /(?<=\t)\w+/ соответствует слову, следующему за символом табуляции, и символ табуляции не включается в $& . Фрагмент, соответствующий заглядыванию назад, должен иметь фиксированную ширину. (?pattern ) Несоответствие с заглядыванием назад без запоминания найденного соответствия. Например, выражение /(?6.4.6. Операции с регулярными выражениями

До сих пор мы заключали регулярные выражения в символы // . На самом деле символы-ограничители регулярного выражения определяются q-операцией , которую мы к ним применяем. В этом разделе подробно описаны все операции языка PERL с регулярными выражениями.

6.4.6.1. Сопоставление с образцом

Синтаксис : /pattern /modifiers m/pattern /modifiers

pattern и возвращает истину или ложь в зависимости от результата сопоставления. Сопоставляемая строка задается левым операндом операции =~ или!~ , например:

$mynumber = "12345"; if ($mynumber =~ /^\d+$/) { # если строка $mynumber состоит из десятичных цифр, то… ... }

Если строка не задана, то производится сопоставление с содержимым специальной переменной $_ . В частности, предыдущий пример можно переписать так:

$_ = "12345"; if (/^\d+$/) { ... }

Если регулярное выражение заключено в // , то начальное m необязательно. Конструкция с начальным m позволяет использовать в качестве ограничителей регулярного выражения любые символы, допустимые в q-операциях. Полезные частные случаи:

Если pattern

Если не задан модификатор g и результат сопоставления присваивается списку, то при неудачном сопоставлении возвращается пустой список. Результат удачного сопоставления зависит от наличия круглых скобок в образце. Если их нет, то возвращается список (1) . В противном случае возвращается список, состоящий из значений переменных $1, $2 и т. д., т. е. список всех запомненных подстрок. Следующий пример

($w1, $w2, $rest) = ($x =~ /^(\S+)\s+(\S+)\s*(.*)/);

заносит в переменную $w1 первое слово строки $x , в переменную $w2 ее второе слово, а в переменную $rest — остаток этой строки.

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

$_ = "12:23:45"; @result = /\d+/g; foreach $elem (@result) { print "$elem\n"; }

выведет на экран строки 12 , 23 и 45 .

В скалярном контексте сопоставление с модификатором g каждый раз ищет следующее соответствие образцу и возвращает истину или ложь в зависимости от результата поиска. Позиция в строке после последнего сопоставления может быть считана или изменена функцией pos() . Неудачный поиск обычно сбрасывает позицию поиска в нуль, но мы можем избежать этого, добавив модификатор c . Изменение строки также приводит к сбросу позиции поиска в ней.

Дополнительные возможности предоставляет метасимвол \G , который имеет смысл только в сочетании с модификатором g . Этот метасимвол соответствует текущей позиции поиска в строке. Использование конструкции m/\G…/gc удобно, в частности, для написания лексических анализаторов, выполняющих различные действия для встреченных в анализируемом тексте лексем. Следующий пример

$_ = "Word1, word2, and 12345."; LOOP: { print("number "), redo LOOP if /\G\d+\b[,.;]?\s*/gc; print("word "), redo LOOP if /\G+\b[,.;]?\s*/gc; print("unknown "), redo LOOP if /\G[^A-Za-z0-9]+/gc; }

выведет на экран строку word word word number .

6.4.6.2. Единственное сопоставление с образцом

Синтаксис : ?pattern ? m?pattern ?

Эта конструкция полностью аналогична конструкции m/pattern / с единственным отличием: успешное сопоставление с образцом выполняется только один раз между вызовами функции reset() . Это удобно, например, когда нам нужно найти только первое вхождение образца в каждом файле из просматриваемого набора, например:

While (<>) { if (?^$?) { ... # обработать первую пустую строку файла } } continue { reset if eof; # сбросить статус?? для следующего файла }

6.4.6.3. Создание регулярного выражения

Синтаксис : qr/string /modifiers

Эта конструкция создает регулярное выражение с текстом string и модификаторами modifiers и компилирует его. Если ограничителями являются символы "" , то интерполяция строки string o

Однажды созданное регулярное выражение может употребляться как самостоятельно, так и в качестве фрагмента других регулярных выражений. Примеры:

$re = qr/\d+/; $string =~ /\s*${re}\s*/; # включение в другое регулярное выражение $string =~ $re; # самостоятельное использование $string =~ /$re/; # то же самое $re = qr/$header/is; s/$re/text/; # то же, что s/$header/text/is

6.4.6.4. Подстановка

Синтаксис : s/pattern /string /modifiers

Эта операция сопоставляет заданную строку с образцом pattern и заменяет найденные фрагменты на строку string . Она возвращает количество произведенных замен или ложь (точнее, пустую строку), если сопоставление закончилось неудачей. Сопоставляемая строка задается левым операндом операции =~ или!~ . Она должна быть скалярной переменной, элементом массива или элементом ассоциативного массива, например:

$path = "/usr/bin/perl"; $path =~ s|/usr/bin|/usr/local/bin|;

$_ = "/usr/bin/perl"; s|/usr/bin|/usr/local/bin|;

Помимо стандартных, здесь могут употребляться следующие модификаторы:

pattern string должен иметь собственную пару ограничителей, например s(foo) или s/bar/ .

Если ограничителями являются символы "" , то интерполяция строки pattern не производится. В остальных случаях происходит интерполяция образца и если он содержит переменные, то при каждом сопоставлении производится его компиляция. Чтобы избежать этого, используйте модификатор o (разумеется, если вы уверены, что значения переменных, входящих в образец, остаются неизменными).

Если pattern является пустой строкой, то вместо него используется последнее успешно сопоставленное регулярное выражение.

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

Модификатор e указывает, что string является выражением. В этом случае к string сначала применяется функция eval() , а затем производится подстановка. Пример:

$_ = "123"; s/\d+/$&*2/e; # $_ = "246" s/\d/$&*2/eg; # то же самое

Приведем еще несколько типичных примеров использования операции подстановки. Удаление комментариев вида /*…*/ из текста Java- или C-программы:

$program =~ s { /\* # Начало комментария.*? # Минимальное количество символов \*/ # Конец комментария }gsx;

Удаление начальных и конечных пробелов в строке $var:

For ($var) { s/^\s+//; s/\s+$//; }

Перестановка двух первых полей в $_ . Обратите внимание, что в строке замены используются переменные $1 и $2 , а не метасимволы \1 и \2:

S/([^ ]*) *([^ ]*)/$2 $1/;

Замена табуляций на пробелы с выравниванием по колонкам, кратным восьми:

1 while s/\t+/" " x (length($&)*8 - length($`)%8)/e;

6.4.6.5. Транслитерация

Синтаксис : tr/list1 /list2 /modifiers y/list1 /list2 /modifiers

Транслитерация состоит в замене всех символов из списка list1 соответствующими символами из списка list2 . Она возвращает количество замененных или удаленных символов. Списки должны состоять из отдельных символов и/или диапазонов вида a-z . Преобразуемая строка задается левым операндом операции =~ или!~ . Она должна быть скалярной переменной, элементом массива или элементом ассоциативного массива, например:

$test = "ABCDEabcde"; $test =~ tr/A-Z/a-z/; # замена строчных букв на прописные

Если строка не задана, то операция подстановки производится над специальной переменной $_ . В частности, предыдущий пример можно переписать так:

$_ = "ABCDEabcde"; tr/A-Z/a-z/;

Мы можем использовать вместо // любой символ, допустимый в q-операциях. Если list1 заключен в парные скобки, то list2 должен иметь собственную пару ограничителей, например tr(A-Z) или tr/a-z/ .

Обычно эта операция называется tr . Синоним y введен для фанатиков редактора sed и используется только ими. Транслитерация поддерживает следующие модификаторы:

Модификатор c вызывает транслитерацию всех символов, не входящих в список list1 . Например, операция tr/a-zA-Z/ /c заменит все символы, не являющиеся латинскими буквами, на пробелы.

По умолчанию, если list2 короче, чем list1 , он дополняется последним своим символом, а если он пуст, то принимается равным list1 (это удобно для подсчета количества символов определенного класса в строке). Модификатор d изменяет эти правила: все символы из list1 , которым нет соответствия в list2 , удаляются из строки. Например, операция tr/a-zA-Z//cd удалит из строки все символы, не являющиеся латинскими буквами.

Модификатор s удаляет повторы: если несколько символов подряд заменились на один и тот же символ, то будет оставлено только один экземпляр этого символа. Например, операция tr/ / /s удаляет в строке повторяющиеся пробелы.

Модификаторы C и U предназначены для перекодировки символов из системной кодировки в UTF-8 и обратно. Первый из них указывает на исходную кодировку, а второй — на кодировку результата. Например, tr/\0-\xFF//CU перекодирует строку из системной кодировки в UTF-8, а tr/\0-\xFF//UC выполнит обратную перекодировку.

Транслитерация производится без интерполяции списков символов, поэтому для использования в ней переменных необходимо вызвать функцию eval() , например.

  1. Заменить множественные пробелы и нетекстовые символы на одиночные пробелы:

    $text = "Here is the text."
    $text =~ tr[\000-\040\177\377][\040]s;
    print $text;
    Here is the text.

  2. Сократить удвоенные, утроенные и т.д. буквы:

    $text = "Here is the texxxxxxt.";
    $text =~ tr/a-zA-Z/s;
    print $text;
    Here is the text.

  3. Пересчитать количество небуквенных символов:

    $xcount=($text =~ tr/A-Za-z//c);

  4. Обнулить восьмой бит символов, удалить нетекстовые символы:

    $text =- tr{\200-\377}{\000-\l77};
    $text =~ tr[\000-\037\177]d;

  5. Заменить нетекстовые и 8-битные символы на одиночный пробел:

    $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) можно поместить произвольный код, включая вызовы программ.

Поиск n-го совпадения

С помощью модификатора 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?

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

  • *? - ноль или несколько совпадений,
  • +? - одно или несколько совпадений,
  • ?? - ноль совпадений или одно совпадение,
  • {n}? - ровно n совпадений,
  • {n,}? - по крайней мере n совпадений,
  • {n,m}? - совпадений по крайней мере n , но не более, чем m.

Оратите внимание, что смыслквантификатора от этого не меняется; меняется только поведение алгоритма поиска. Если в процессе сопоставления шаблона и текста прототип определяется однозначно, то алгоритм поиска с возвратами увеличит "жадность" такого квантификатора точно так же, как он ограничивает аппетит собрата. Однако если выбор неоднозначен, то результат поиска будет другим:

$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 , в том числе и пустых.

Модификаторы:

  • /i игнорировать регистр
  • /x игнорировать пропуски в шаблоне и разрешить комментарии.
  • /g модификатор разрешающий выполнение поиска/замены везде, где это возможно
  • /gc не сбрасывается позиция при неудачном поиске.
  • /s разрешается совпрадение. с \n , игнорируется $* .
  • /m разрешить совпадение ^ и $ для начала и конца строки во внутренних переводах строк
  • /o однократная компиляция
  • /e правая часть s/// представляет собой выполняемый код
  • /ee правая часть s/// выполняется, после чего возвращаемое значение интерпретируется снова.

при вызове 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 текущей директории к нижнему регистру.

Язык, созданный первоначально с главной целью облегчить обработку большого количества отчетов, просто обязан располагать развитыми средствами для работы с текстом. Напомним, что в среде UNIX, из которой вышел язык Perl, средства для обработки текстовых строк имеются в различных утилитах: sed, awk, grep, cut, а командный интерпретатор shell, также обладающий некоторыми средствами для обработки строк, позволяет организовать совместную работу этих утилит, передавая выход одной программы на вход другой через механизм, называемый конвейером. Такой подход требует написания достаточно изощренных сценариев на языке shell в сочетании с обращением к внутренним командам утилит обработки текста sed или awk. Язык Perl, являясь средством создания программ-сценариев, в то же время один обладает всеми возможностями перечисленных утилит и даже их превосходит. Типичная задача, возникающая при обработке текстового файла, заключается в том, чтобы найти в нем фрагмент, удовлетворяющий заданным условиям, и выполнить над найденным фрагментом некоторую операцию: удалить, заменить на другой фрагмент, извлечь для дальнейшего использования и т. д. Условия поиска можно достаточно просто выразить словами. Например: найти строку, содержащую слово Perl. Или: найти все фрагменты, находящиеся в конце строки и содержащие две цифры, за которыми следует произвольное количество прописных букв. Для формализованной записи подобных условий используются регулярные выражения, позволяющие описать образец, или шаблон поиска при помощи специальных правил. Манипуляции с регулярными выражениями осуществляются при помощи соответствующих операций, которые мы также рассмотрим в этой главе.

Регулярные выражения

Регулярное выражение, по сути, представляет собой набор правил для описания текстовых строк. Сами правила записываются в виде последовательности обычных символов и метасимволов, которая затем в качестве образца используется в операциях поиска и замены текста. Метасимволы - это символы, имеющие в регулярном выражении специальное значение. Пользователи DOS/Windows хорошо знают метасимвол *, используемый для порождения имен файлов и обозначающий любую допустимую последовательность. Регулярные выражения используются многими программами UNIX, в том числе интерпретатором shell. Каждая из них использует свое множество метасимволов. В большинстве случаев метасимволы разных программ совпадают.

Метасимволы

В языке Perl к метасимволам относятся следующие символы: "\", ".", "^", "$", "|", "[", "]", "(", ")", "*", "+", "?", "{", "}" Различные метасимволы выполняют в регулярном выражении разные функции, в частности, используются для обозначения одиночного символа или группы символов, обозначают привязку к определенному месту строки, число возможных повторений отдельных элементов, возможность выбора из нескольких вариантов и т. д. Регулярное выражение, подобно арифметическому выражению, строится с соблюдением определенных правил. В нем можно выделить операнды (элементы) и операции. Простейшим регулярным выражением является регулярное выражение, состоящее из одного обычного символа. Обычный символ в регулярном выражении представляет самого себя. Соответственно, последовательность обычных символов представляет саму себя и не нуждается в дополнительной интерпретации. Для использования в операциях в качестве образца регулярное выражение заключается между двумя одинаковыми символами-ограничителями. Часто в качестве ограничителя используется символ косая черта (/). Например, образцу /Perl/ будут соответствовать все строки, содержащие слово Perl, Если в регулярном выражении какой-либо метасимвол требуется использовать в буквальном, а не специальном значении, его нужно экранировать, или маскировать, при помощи другого метасимвола - \. Например, образцу /\\\*/ соответствует фрагмент текста \*. Здесь первый метасимвол \ экранирует второй метасимвол \, а третий метасимвол \ экранирует метасимвол * Метасимвол. представляет любой одиночный символ, кроме символа новой строки. Так, образцу /./ будет соответствовать любая непустая строка. Если в операциях сопоставления с образцом установлен флаг s, то метасимволу. соответствует также и символ новой строки. Метасимвол [ используется в конструкции [...] для представления любого одиночного символа из числа заключенных в скобки, то есть он представляет класс символов. Два символа, соединенные знаком минус, задают диапазон значений, например задает все прописные и строчные буквы английского алфавита. Если первым символом в скобках является символ ^, вся конструкция обозначает любой символ, не входящий в число перечисленных в скобках. Например, [^0-9] обозначает все нецифровые символы. Ниже мы рассмотрим и другие способы представления классов символов. Метасимволы ^ и $ используются для задания привязки к определенному месту строки. Метасимвол ^ в качестве первого символа регулярного выражения обозначает начало строки. Метасимвол $ в качестве последнего символа регулярного выражения обозначает конец строки. Например, следующим образцам соответствуют: /^$/ - пустая строка (начало и конец, между которыми пусто); /^Perl/ - слово Perl в начале строки; /Perl$/ - слово Perl в конце строки. Метасимвол | можно рассматривать как символ операции, задающей выбор из нескольких вариантов (подобно логической операции ИЛИ). Например, образцу /а | b | с/ соответствует фрагмент текста, содержащий любой из символов а, b, с. Если вариантами выбора являются одиночные символы, как в данном примере, то лучше использовать конструкцию, определяющую класс символов, в данном случае . Но, в отличие от конструкции [...], операция | применима и тогда, когда вариантами выбора являются последовательности символов. Например, образцу /Word|Excel|Windows/ соответствует фрагмент текста, содержащий любое из слов Word, Excel, Windows. Следующая группа метасимволов служит в качестве коэффициентов, или множителей, определяющих количество возможных повторений отдельных атомарных элементов регулярного выражения. r* - нуль и более повторений r; r+ - одно и более повторений r; r? - нуль или одно повторение r; r{n} - ровно n повторений r; r{n,} - n и более повторений r; r{n,m} - минимум n, максимум m повторений r. Атомарные элементы, или атомы, - это простейшие элементы, из которых строится регулярное выражение. Это не обязательно одиночный символ. Вот несколько примеров использования множителей в регулярных выражениях: /.*/ - любая строка; /.+/ - любая непустая строка; /{3}/ - любая последовательность из трех цифр; /\[+/ - последовательность, состоящая из любого числа символов [. В первых двух примерах атомом является метасимвол. (точка). В третьем образце в качестве атома выступает конструкция , определяющая класс цифровых символов. В четвертом образце атом - это пара символов \[, включающая метасимвол \, отменяющий специальное значение следующего за ним метасимвола [. Полный список атомов мы приведем после изучения всех необходимых синтаксических конструкций. Алгоритм, применяемый в операциях поиска и замены для обработки регулярных выражений, содержащих множители, является «жадным»: он пытается найти для образца, снабженного множителем, максимальный сопоставимый фрагмент текста. Рассмотрим, например, что происходит при поиске в строке: «Скроен колпак не по-колпаковски, надо колпак переколпаковать» фрагмента, удовлетворяющего образцу /.*колпак/. Алгоритм найдет максимальный фрагмент, удовлетворяющий выражению.* (вся строка без завершающего символа новой строки), затем начнет двигаться назад, отбрасывая в найденном фрагменте по одному символу, до тех пор, пока не будет достигнуто соответствие с образцом. Найденный фрагмент будет иметь вид: «Скроен колпак не по-колпаковски, надо колпак переколпак». Можно заставить алгоритм работать иначе, снабдив множитель * модификатором?. В этом случае алгоритм из «жадного» превращается в «ленивый» и будет для образца, снабженного множителем, искать минимальный соответствующий фрагмент. «Ленивый» алгоритм для множителя *? начнет поиск в строке с пустого фрагмента "", добавляя к нему по одному символу из строки до тех пор, пока не достигнет соответствия с образцом. В этом случае найденный фрагмент будет иметь вид: «Скроен колпак». Все сказанное справедливо и для других множителей. Например, в строке "1234567" будет найден: для образца /\d*/ - максимальный фрагмент "1234567"; для образца /\d+/ - максимальный фрагмент "1234567"; для образца/\d?/ - максимальный фрагмент "1"; для образца /\d{2,5}/ - максимальный фрагмент "12345"; для образца /\d*?/ - минимальный фрагмент ""; для образца /\d+?/ - минимальный фрагмент "1"; для образца /\d??/ - минимальный фрагмент ""; для образца /\d{2,5}?/ - минимальный фрагмент "12".

Метапоследовательности

Символ \, непосредственно предшествующий одному из метасимволов, отменяет специальное значение последнего. Если же символ \ непосредственно предшествует обычному символу, то, напротив, такая последовательность символов во многих случаях приобретает специальное значение. Подобного рода последовательности будем называть метапоследовательностями, Метапоследовательности в регулярном выражении служат, в основном, для представления отдельных символов, классов символов или определенного места в строке, дополняя и иногда дублируя функции метасимволов. Рассмотрим существующие метапоследовательности.
  • \nnn - представляет символ, восьмеричный код которого равен nnn. Например, последовательность \120\145\162\154 представляет слово Perl (\120 - восьмеричный код буквы Р, \145 - буквы е, \162 - буквы r, \154 - буквы l).
  • \xnn - представляет символ, шестнадцатеричный код которого равен nn. Слово Perl, например, представляется последовательностью \x50\x65\x72\x6C.
  • \cn - представляет управляющий символ, который генерируется при нажатии комбинации клавиш Ctrl+n, где n- символ, например \cD соответствует Ctrl+D.
  • \$- символ $.
  • \@ - символ @.
  • \% - символ %
  • \а - представляет символ с десятичным ASCII-кодом 7 (звонок). При выводе производит звуковой сигнал.
  • \е - символ Esc, десятичный ASCII-код 27.
  • \f - символ перевода страницы, десятичный ASCII-код 12.
  • \n - символ новой строки, десятичный ASCII-код 10.
  • \r - символ «возврат каретки», десятичный ASCII-код 13.
  • \t - символ горизонтальной табуляции, десятичный ASCII-код 9.
  • \v - символ вертикальной табуляции, десятичный ASCII-код 11.
  • \s - представляет класс пробельных символов. К пробельным символам относятся пробел, символ табуляции, возврат каретки, символ новой строки и символ перевода страницы. То же самое, что и[ \t,\r,\n,\f].
  • \S - представляет класс непробельных символов, то же самое, что и класс [^ \t, \r,\n,\f].
  • \d - класс цифровых символов, тоже, что и .
  • \D - класс нецифровых символов, то же, что и [^0-9].
  • \w - представляет класс буквенно-цифровых символов, состоящий из букв, цифр и символа подчеркивания _. То же самое, что и . Обратите внимание, что в этот класс входят только буквы английского алфавита.
  • \W - представляет класс небуквенно-цифровых символов. То же самое, что и выражение [^a-zA-Z_0-9].
  • \А - обозначает начало строки.
  • \Z - обозначает конец строки.

ПРИМЕЧАНИЕ Последовательность \А эквивалентна метасимволу ^ в начале регулярного выражения, а последовательность \Z - метасимволу $ в конце регулярного выражения, за исключением одного случая. Назовем строку, содержащую внутри себя символы новой строки (ASCII 10), мультистрокой. Фактически мультистрока состоит из отдельных строк, разделенных ограничителями - символами новой строки. При выводе мультистрока отображается в виде нескольких строк. Если к мультистроке применяется операция поиска или замены с опцией /m, то последовательности \А и \Z обозначают соответственно начало и конец всей мультистроки, а метасимволам ^ и $ соответствуют еще и границы внутренних строк, образующих мультистроку.

  • \b - обозначает границы слова. Под словом понимается последовательность символов из класса \w. Граница слова определяется как точка между символами из класса \w и символами из класса \W.
  • \В - обозначает не-границы слова, то есть класс символов [^\b].
  • \l - означает, что следующий символ регулярного выражения преобразуется в нижний регистр. Например, запись /\lP/ означает, что символ Р будет преобразован в нижний регистр, после чего новый образец /p/ может быть использован в соответствующей операции поиска или замены,
  • \u - означает, что следующий символ регулярного выражения преобразуется в верхний регистр.
  • \L...\Е - означает, что все символы в регулярном выражении между \L и \Е преобразуются в нижний регистр.
  • \U...\Е -означает, что все символы в регулярном выражении между \U и \Е преобразуются в верхний регистр.
  • \Q...\Е - означает, что все метасимволы в регулярном выражении между \Q и \Е экранируются при помощи символа \. Например, запись /\Q^*?+\Е/ эквивалентна записи /\^\*\?\+/.
  • \G - обозначает точку, в которой закончился предыдущий поиск m//g (см. описание операции поиска m//).

Атомы

Из всех метасимволов, перечисленных в начале параграфа, нам осталось рассмотреть метасимволы (и). Они служат для группирования ряда элементов, входящих в состав образца, в один элемент. Например, образцу /(abc)+/ соответствует строка, состоящая из одного или более повторений последовательности abc, в то время как образцу /abc+/ - строка, состоящая из начальных символов ab, за которыми следует один или более символов с. Теперь мы можем перечислить атомы, из которых строится регулярное выражение.
  • Регулярное выражение в скобках, представляющее несколько элементов, сгруппированных в один элемент.
  • Любой обычный символ (не метасимвол).
  • Символ. , представляющий любой одиночный символ, кроме символа новой строки.
  • Конструкция [...], представляющая класс символов, перечисленных в квадратных скобках.
  • Метапоследовательность, представляющая символ или класс символов: \а, \n, \r, \t, \f, \e, \d, \D, \w, \W, \s, \S.
  • Метапоследовательность вида \nnn, определяющая символ при помощи его восьмеричного ASCII-кода nnn.
  • Метапоследовательность вида \xnn, определяющая символ при помощи его шестнадцатеричного ASCII-кода nn.
  • Метапоследовательность вида \cn, представляющая управляющий символ Ctrl+n.
  • Конструкция вида \number, представляющая обратную ссылку (см. следующий раздел).
  • Любая конструкция вида \character, не имеющая специального значения, а представляющая собственно символ character, например: \*, \у, \h. Напомним, что в регулярном выражении множители *, +, ?, {n,m} применяются именно к атому, расположенному непосредственно слева.

    Обратные ссылки

    Ранее мы установили, что группу элементов регулярного выражения можно заключить в скобки и рассматривать как один элемент. Заключение группы элементов в скобки имеет дополнительный и весьма полезный эффект. Если в результате поиска будет найден фрагмент текста, соответствующий образцу, заключенному в скобки, то этот фрагмент будет сохранен в специальной переменной, и внутри регулярного выражения к нему можно будет обратиться, используя запись \number, где number- номер конструкции (...) в исходном регулярном выражении. Запись \number, указывающую на найденный по образцу фрагмент текста, будем называть обратной ссылкой. Можно задать любое количество конструкций вида (...) и ссылаться на соответствующие найденные фрагменты текста как на \1, \2 и т. д. Например, образцу /(.+)-\1/ соответствуют слова «ха-ха», «хи-хи», «ку-ку!> и т. п., а образцу /(.)(.).?\2\1/ соответствуют все палиндромы из четырех или пяти букв, (Палиндром - слово или предложение, которое одинаково читается слева направо и справа налево.) Внутри образца конструкция \n (n= 1,...,9) всегда обозначает обратную ссылку. Запись вида \nn также интерпретируется как обратная ссылка, но только в том случае, если в исходном выражении задано не менее, чем nn скобочных конструкций вида (...). Иначе запись \nn обозначает символ с восьмеричным кодом nn. Для ссылки на найденный фрагмент текста за пределами регулярного выражения, например, при задании замещающего текста в операции замены, вместо записи \number используется запись $number. Например, операция замены $str =~ s/(\S+)\s+(\S+)/$2 $1/ меняет местами первые два слова в строке $str. Область действия переменных $1, $2 и т. д. распространяется до наступления одного из следующих событий: конец текущего блока; конец строки, являющейся аргументом функции eval; следующее совпадение с образцом. Аналогичным образом определяется область действия и для следующих предопределенных переменных, используемых в операциях сопоставления с образцом:
    • $& - часть строки, найденная при последней операции сопоставления с образцом;
    • $` - часть строки, стоящая перед совпавшей частью при последней успешной операции сопоставления с образцом;
    • $" - часть строки, стоящая после совпавшей части при последней успешной операции сопоставления с образцом.
    Например, в результате выполнения операции поиска $str =~ m/two/ в строке $str = "one two three" образца /two/ будут присвоены следующие значения переменным:
    • $& - "two";
    • $` - "one";
    • $" - "three".
    Эти значения будут сохраняться до наступления одного из перечисленных выше событий, и их можно использовать, например, для формирования строки с обратным порядком следования слов: $rstr=$".$&.$`. Строка $rstr будет иметь вид: "three two one". Следует отметить, что, если обращение к одной из переменных $&, $`, $" встречается где-либо в программе, то интерпретатор perl будет вычислять и запоминать их для каждой операции сопоставления с образцом, что, в свою очередь, замедляет выполнение всей программы. Поэтому не следует использовать данные переменные без особой необходимости.

    Расширенный синтаксис регулярных выражений

    Выше мы использовали скобки для группирования нескольких элементов регулярного выражения в один элемент. Побочным эффектом данной операции является запоминание найденного фрагмента текста, соответствующего образцу, заключенному в скобки, в специальной переменной. Если скобки используются только для группирования элементов регулярного выражения, то найденный фрагмент текста можно не запоминать. Для этого после открывающей скобки (следует поместить конструкцию?:, например в случае задания альтернативы - /(?:Реrl|реrl)/. Конструкция (?:pattern) относится к классу конструкций общего вида (?...), добавляющих новые возможности для задания образцов за счет расширения синтаксиса регулярного выражения, а не за счет введения новых метасимволов или метапоследовательностей. Символ, следующий за символом?, определяет функцию, выполняемую данной синтаксической конструкцией. В настоящее время определены около десяти расширенных конструкций регулярного выражения, большая часть которых рассмотрена в данном разделе. Оставшиеся конструкции, на наш взгляд, не являются необходимыми для первоначального знакомства с языком. (?#text) - комментарий. Текст после символа # и до закрывающей скобки) игнорируется интерпретатором и используется для добавления комментария непосредственно в регулярное выражение. (?imsx-imsx: pattern) - использовать скобки только для группирования элементов без создания обратных ссылок. Символы imsx-imsx между вопросительным знаком и двоеточием интерпретируются как флаги, модифицирующие функцию данного выражения (см. ниже). (?=pattern) - следующий фрагмент в тексте должен соответствовать образцу pattern. Обычно образец для операций поиска или замены задается при помощи регулярного выражения. Результатом операции поиска является фрагмент, соответствующий образцу, который сохраняется в специальной переменной $&. Конструкция (?=pattern) в составе регулярного выражения позволяет задать условие поиска, не включая найденный фрагмент, соответствующий образцу pattern, в результат, сохраняемый в переменной $&. Конструкция (?=pattern) в регулярном выражении задает условие, что следующий фрагмент текста должен удовлетворять образцу pattern. Обращаем внимание на слово следующий. Данная конструкция неприменима для задания условия, что предыдущий фрагмент текста должен соответствовать заданному образцу. Например, образцу/b+(?=с+)/соответствует часть строки, состоящая из одной или более литер b, за которыми следуют одна или более литер с, причем найденный фрагмент текста будет содержать только последовательность литер b без последовательности литер с. Рассмотрим, например, строку: $str = "aaabbbcccddd"; В результате операции поиска $str =~ m/b+(?=c+)/; будут сохранены следующие значения в специальных переменных: S` - ааа, $& - bbb, $" - cccddd. Если в операции поиска указать образец /b+с+/, то значения специальных переменных будут следующими: S` - ааа, $&- bbbccc, $" - ddd. B свою очередь, операция поиска по образцу /(?=b+)с+/ в нашем примере не даст результата. Данный образец задает условие, что следующий фрагмент текста должен содержать непустую последовательность литер b. В нашей строке такой фрагмент будет найден, это фрагмент bbb, но он не будет включен в результат поиска. Следующий фрагмент, в соответствии с образцом, должен представлять непустую последовательность литер с, но в нашем случае этого соответствия не будет, так как мы остановились перед фрагментом bbb, не включив его в результат, и следующим фрагментом поэтому будет bbb, а не ссс. Конструкцию (?=pattern) будем называть регулярным выражением с положительным постусловием. (?!pattern) - конструкция в регулярном выражении задает условие, что следующий фрагмент текста не должен удовлетворять образцу pattern. Найденный фрагмент не запоминается в переменной $&. Например, результат операции поиска $str =~ m/b+(?!с+)/; в рассмотренной выше строке $str будет зафиксирован в следующих значениях специальных переменных: S` - ааа, S& - bb, $" - bcccddd. Найденная подстрока соответствует образцу: она состоит из двух литер bb, за которыми не следует последовательность литер с. По аналогии с предыдущей конструкцией данную конструкцию назовем регулярным выражением с отрицательным постусловием. (?$str =~ m/(?<=b)b+/; значения специальных переменных будут распределены следующим образом: S` - ааа, $& - bb, $" - cccddd. Данную конструкцию назовем регулярным выражением с положительным предусловием. (?
  • i - поиск без учета регистра;
  • m - строка трактуется как мультистрока, состоящая из нескольких строк, разделенных символом новой строки;
  • s - строка трактуется как одна строка, в этом случае метасимволу. соответствует любой одиночный символ, включая символ новой строки;
  • x - разрешается использовать в образцах пробелы и комментарии. При использовании флага х пробелы в образцах игнорируются. Признаком комментария является символ #, как и в основном тексте Perl-программы. Пробелы позволяют сделать образец лучше читаемым.
Одна из литер i , m, s, x после знака - обозначает отмену соответствующего флага. При помощи данной расширенной конструкции можно задать, например, следующий образец: /(?ix) perl # игнорирование регистра при поиске/ Флаг i предписывает не учитывать регистр в операциях сопоставления с образцом, так что образцу будет соответствовать и слово «perl», и слово «Perl». Флаг х позволяет выделить слово «perl» пробелами и использовать непосредственно в образце комментарий. И пробелы, и комментарий не будут учитываться в операции сопоставления с образцом.

Сводка результатов

Изложенное в данном параграфе можно суммировать в виде набора правил, которыми следует руководствоваться при работе с регулярными выражениями.
  1. Любой одиночный символ, не являющийся метасимволом, представляет самого себя.
  2. Специальное значение метасимвола можно отменить, поместив перед ним специальный экранирующий метасимвол \.
  3. Можно определить класс символов, заключив их в квадратные скобки. Если первым после открывающей скобки [ является символ ^, то вся конструкция обозначает класс символов, не входящих в число перечисленных в скобках. Внутри скобок два символа, соединенные знаком -, определяют диапазон. Чтобы включить в состав класса символ -, его следует поместить в начале или в конце списка либо экранировать при помощи символа \.
  4. Символы можно задавать при помощи метапоследовательностей, состоящих из символа \, за которым следует обычный символ или последовательность символов.
  5. Альтернативный выбор задается перечислением вариантов, разделенных символом |. Обычно вся конструкция при этом заключается в круглые скобки.
  6. Внутри регулярного выражения можно выделить подобразец, заключив его в круглые скобки. На n-ю конструкцию в скобках можно затем сослаться, используя нотацию \n внутри и $n - вне регулярного выражения.
В заключение приведем сводку метасимволов и метапоследовательностей, рассмотренных в данной главе. Таблица 8.1. Символы, имеющие специальное значение в регулярном выражении Perl
Метасимвол Интерпретация
\ Отменяет (экранирует) специальное значение следующего за ним метасимвола
. Любой одиночный символ, кроме символа новой строки. Любой одиночный символ, включая символ новой строки, если в операции сопоставления с образцом задан флаг s
^ Обозначает начало строки, если является первым символом образца
$ Обозначает коней строки, если является последним символом образца
| Разделяет альтернативные варианты
[...] Любой одиночный символ из числа перечисленных в квадратных скобках. Пара символов, разделенных знаком минус, задает диапазон символов. Например, задает все прописные и строчные буквы английского алфавита. Если первым символом в скобках является символ ^, вся конструкция обозначает любой символ, не входящий в число перечисленных в скобках. Внутри скобок символы. * [ и \ теряют свое специальное значение.
(...) Группирование элементов образца в один элемент
* Нуль и более повторений регулярного выражения, стоящего непосредственно перед *
+ Одно или более повторений регулярного выражения, стоящего Непосредственно перед +
? Одно или ни одного повторения регулярного выражения, стоящего непосредственно перед?
{n, m} Минимальное n и максимальное m число повторений регулярного выражения, стоящего перед {n, m}. Конструкция {n} означает ровно n повторений, {n,} - минимум n повторений

Таблица 8.2. Метапоследовательности в регулярных выражениях Perl
Метапоследовательность Значение
\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 Обозначает конец строки

> Регулярные выражения в 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), говоря о
том, как ему нужно разбирать рабочее значение.

Модификаторы для оператора сравнения:

  • x - позволяет использовать расширенные регулярные выражения;

Модификаторы для оператора подстановки:

  • e - вычисляет подстановочное выражение перед подстановкой;
  • g - находит все найденные подстроки;
  • i - игнорирует регистр символов в строке;
  • m - рассматривает строку как многострочное значение;
  • s - рассматривает строку как однострочое значение;
  • x - позволяет использовать расширенные регулярные выражения.

Модификаторы

$_ = "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 содержит "."

Переменные $1..$9

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

$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.

В данной главе описывается синтаксис регулярных выражений. Чаще всего в Перл они используюстя в операторах поиска и замены таких как s// m/ операторах связки =~ или!= и т.д.

Как правило все эти операторы имеют схожие опции такие как:

i - не различать строчные и заглавные буквы
m - считать строку многострочной
s - однострочная строка
x - расширенный синтаксис (использование пробелов и комментариев)

Обычно все эти опции обозначают как "/x". Их можно использовать даже внутри шаблонов использую новую конструкцию (?...)

Регулярные выражения или шаблоны (pattern) то же самое что и regexp процедуры в Юниксе. Выражения и синтаксис заимствован из свободно распространяемых процедур V8 Генри Спенсера (Henry Spencer) там же они подробно и описаны.

В шаблонах используются следующие метасимволы (символы обозначающие группы других символов) часто называемых egrep - стандартом:

\ - считать следующий метасимвол как обычный символ
^ - начало строки
. - один произвольный символ. Кроме "\n" - конец строки
$ - конец строки
| - альтернатива (или)
() - группировка
- класс символов

Метасимволы имеют модификаторы (пишутся после метасимвола):

* - повторяется 0 или большее число раз
+ - повторяется 1 или большее число раз
? - 1 или 0 раз
{n} - точно n раз
{n,} - по меньшей мере раз
{n,m} - не менше n, но и не больше m

Во все других случаях фигурные скобки считаются обычными (регулярными) символами. Таким образом "*" эквивалентна {0,} , "+" - {1,} и "?" - {0,1}. n и m не могут быть больше 65536.

По умолчанию действие метасимволов "жадно" (greedy). Совпадение распространяется столько раз сколько возможно не учитывая результат действия следуюющих метасимволов. Если вы хотите "уменьшить их аппетит" то используйте символ "?". Это не изменяет значение метасимволов просто уменьшает распространение. Таким образом:

*? - станет 0 и более
+? - 1 и более
?? - 0 или 1 раз
{n}? - точно n раз
{n,}? - не меньше n раз
{n,m}? - больше или равно n и меньше m раз

Шаблоны работают так же, как и двойные кавычки поэтому в них можно использовать `\` - символы (бакслэш-символы):

\t - символ табуляции
\n - новая строка
\r - перевод каретки
\а - перевол формата
\v - вертикальная табуляция
\a - звонок
\e - escape
\033 - восьмеричная запись символа
\x1A - шестнадцатеричная
\c[ - control символ
\l - нижний регистр следующего символа
\u - верхний регистр следующего символа
\L - все символы в нижнем регистре до \E
\U - в верхнем регистре до \E
\E - ограничитель смены регистра
\Q - отмена действия как метасимвола

Дополнительно в Перл добавлены следующие метасимволы:

\w - алфавитно-цифровой или "_" символ
\W - не алфавитно-цифровой или "_" символ
\s - один пробел
\S - один не пробел
\d - одна цифра
\D - одна не цифра

Обратите внимание что все это "один" символ. Для обозначения последовательности применяйте модификаторы. Так:

\w+ - слово
\d+ - целое число
[+-]?\d+ - целое со знаком
[+-]?\d+\.?\d* - число с точкой

Кроме того существуют мнимые метасимволы. Обозначающие не существующие символы в месте смены значения. Такие как:

\b - граница слова
\B - не граница слова
\A - начало строки
\Z - конец строки
\G - конец действия m//g

Граница слова (\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" }

Перл версии 5 содержит дополнительные конструкции шаблонов:

(?#комментарий) - комментарий в теле шаблона.
(?:шаблон) - группировка как и "()" но без обратной ссылки
(?=шаблон) - "заглядывание" вперед.

Например /\w+(?=\t)/ соответствует слову, за которым идет табуляция, но символ "\t" не включается в результат.

$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)

  1. Любой символ обозначает себя самого если это не метасимвол. Если вам нужно отменить действие метасимвола то поставьте перед ним "\".
  2. Строка символов обозначает строку этих символов.
  3. Множество возможных символов (класс) заключается в квадратные скобки "" это значит что в данном месте может стоять один из указанных в скобках символ. Если первый символ в скобках это "^" - значит не один из указанных символов не может стоять в данном месте выражения. Внутри класса можно употреблять символ "-" обозначающий диаппазон символов. Например a-z один из малых букв латинского алфавита, 0-9 - цифра и т.д.
  4. Все символы, включая специальные можно обозначать с помощью "\" как в языке С.
  5. Альтернативные последовательности разделяются символом "|" Заметьте, что внутри квадратных скобок это обычный символ.
  6. Внутри регулярного выражения можно указыват "подшаблоны", заключая их в крунлые скобки и ссылаться на них как "\номер" Первая скобка обозначается как "\1".