Чтение онлайн

ЖАНРЫ

Язык программирования Perl

Шохирев Михаил Васильевич

Шрифт:

m"\+\d{1,}\(\d{3,}\)\d{4,7}"

Для наиболее часто встречающихся квантификаторов предусмотрены удобные односимвольные сокращения:

* повторяется 0 или более раз: то же, что {0,}

? повторяется не более 1 раза: то же, что {0,1}

+ повторяется как минимум 1 раз: то же, что {1,}

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

хотя бы один из перечисленных знаков препинания":

m/\s*\w+[-.,;?]+/ # соответствует, например: ' count--;'

Если квантификатор нужно применить к нескольким шаблонам, то нужно сгруппировать шаблоны, заключив их в круглые скобки. Составим регулярное выражение для поиска IP-адреса, которое находит число, состоящее из одной цифры и более (\d+), за которой может стоять точка (\.?), причем эта последовательность повторяется ровно четыре раза ({4}):

$pattern = '(\d{1,3}\.)\d{1}'; # шаблон для IP-адреса

$text = 'address=208.201.239.36,site=www.perl.com';

$text =~ m/$pattern/; # соответствие: '208.201.239.36'

Программисты шутят: "При составлении шаблона главное, чтобы регулярное выражение соответствовало тому, что нужно, и не соответствовало тому, что не нужно". В следующем примере мы будем искать "более одного символа, за которыми идет буква 'й' и пробел", ожидая, что будет найдено слово 'Какой '. Но нас ожидает неприятный сюрприз:

my $text = 'Какой хороший компакт-диск!';

$text =~ /.+й\s/; # жадный квантификатор

# найдено соответствие: 'Какой хороший '

Это произошло потому, что по умолчанию квантификаторы подразумевают максимальную последовательность символов, соответствующих указанному шаблону. Такое поведение квантификаторов называется "жадным" (greedy quantifier). Чтобы заставить квантификатор вести себя не "жадно", а "лениво" (lazy quantifier), нужно поставить сразу после него символ '?'. Тогда квантификатор будет описывать минимальную последовательность символов, соответствующих образцу. Исправленный с учетом этого образец найдет то, что нужно:

$text =~ /.+?й\s/; # ленивый квантификатор

# найдено соответствие: 'Какой '

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

Часто нам бывает небезразлично, в каком месте содержимое строки совпадет с шаблоном. Мы бы хотели уточнить: "в начале строки", "в конце слова" и так далее. Для того чтобы более точно задать положение в тексте, где должно быть найдено соответствие, в регулярных выражениях можно указывать так называемые утверждения. Утверждение (assertion) не соответствует какому-либо символу, а совпадает с определенной позицией в тексте. Поэтому их можно воспринимать как мнимые символы нулевого размера. Чаще всего используются следующие утверждения (другие приведены в таблице 8.1):

^ позиция в начале строки

$ позиция в конце строки (или перед \n в конце строки)

\b граница слова: позиция между \w и \W или \W и \w

\B любая позиция, кроме границы слова \b

Вот пример шаблонов поиска, где уточняется,

что нужно проверить наличие числа в определенном месте строки:

$log = '20060326 05:55:25 194.67.18.73 ... 200 797';

print "Число в начале\n" if $log =~ /^\d+/;

print "Число в конце\n" if $log =~ /\d+$/;

Утверждение, которое используется для фиксирования части образца относительно положения в строке, иногда называется якорем (anchor). Якори применяются, чтобы указать, в каком именно месте строки нужно искать соответствие образцу.

Когда операция сопоставления находит в строке соответствие указанному регулярному выражению, она присваивает результаты своей работы нескольким специальным переменным:

[x]. в переменную $` помещается часть строки до найденного соответствия;

[x]. в переменную $& помещается часть строки, соответствующая образцу;

[x]. в переменную $' помещается часть строки после найденного соответствия;

[x]. в переменную $+ помещается последнее найденное совпадение для последнего шаблона в скобках.

Если поиск окончился неудачей, то этим переменным новые значения не присваиваются. Посмотрим на примере, что сохранится в этих переменных после поиска такого соответствия:

$htm= "<A HREF='http://regexp.ru/'>Регулярные выражения</A>";

$htm =~ m|HREF=["'](\S+?)["']>|; # поиск URL сайта

При успешном совпадении с шаблоном в специальные переменные будут помещены такие значения:

$` = '<A '

$& = 'HREF='http://regexp.ru/'>'

$' = 'Регулярные выражения</A>'

$+ = 'http://regexp.ru/'

Значениями этих переменных можно пользоваться при успешном сопоставлении с образцом, например:

print $& if $text =~ m/$pattern/; # выведет соответствие

В регулярном выражении можно указать, что при успешном сопоставлении строки с шаблоном найденные соответствия нужно сохранить для дальнейшей обработки. С этой целью запоминаемые части шаблона нужно заключить в круглые скобки. Это также называется захватом значений. Найденные совпадения для всех заключенных в скобки частей шаблона будут доступны через специальные переменные с именами $1, $2 и так далее. Составим регулярное выражение для поиска и сохранения в служебных переменных информации о сайте в том же тексте:

$pattern = q|HREF=["'](\S+?)["']>([^<]+?)</A>|; # шаблон

$htm =~ m/$pattern/; # поиск соответствия в $htm

# в $1 = 'http://regexp.ru/'

# в $2 = 'Регулярные выражения'

Сохраненные совпадения доступны и во время обработки регулярного выражения, но через переменные с именами \1, \2 и так далее. Эти переменные называются обратными ссылками (backreference) на найденные соответствия. Так, например, можно найти два одинаковых слова, стоящих в тексте друг за другом через пробелы (возможно, по ошибке):

Поделиться с друзьями: