$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 и так далее. Составим регулярное выражение для поиска и сохранения в служебных переменных информации о сайте в том же тексте: