Построение эффективных регулярных выражений. Оператор qr/…/ и объекты регулярных выражений.
10.1 Оператор qr/…/
Наряду с операторами q/…/, qq/…/ и qx/…/ в Perl существует оператор qr/…/. Он получает в качестве операнда регулярное выражение, транслирует его и запоминает в переменной, которой присваивается результат. Например:
$_='123abcd'; my $re=qr/((\d+)\w+)/; /$re/; print "$1 $2";
Будет напечатано
123abcd 123
Транслируется регулярное выражение только в момент работы оператора qr/…/. Далее при использовании переменной, которой было присвоено оттранслированное значение, будет применен внутренний байт-код регулярного выражения.
Использование ограничителей вокруг переменной, содержащей оттранслированное регулярное выражение, не обязательно, но в этом примере, где не применяется оператор связывания =~ регулярного выражения с целевой переменной, без ограничителей регулярное выражение работать не будет:
#!/usr/bin/perl -w use strict; $_='123abcd'; my $re=qr/((\d+)\w+)/; $re; print "$1 $2";
Напечатаются сообщения об ошибках:
Useless use of private variable in void context at a.pl line 6. Use of uninitialized value in concatenation (.) or string at a.pl line 7. Use of uninitialized value in concatenation (.) or string at a.pl line 7.
В случае использование оператора связывания все работает нормально:
$_='123abcd'; my $re=qr/((\d+)\w+)/; $_ =~ $re; print "$1 $2";
Печатается
123abcd 123
Записи
$_ =~ $re;
и
$_ =~ /$re/;
не различаются, но в первом случае вы не сможете ничего добавить к регулярному выражению и поставить к нему модификаторы и квантификаторы. Неправильно будет писать ни
$_ =~ ^$re$;
ни
$_ =~ $re$re;
ни
$_ =~ $re.$re;
Если же мы будем использовать ограничители для всего регулярного выражения, то все эти записи кроме последней будут верны:
$_ =~ /^$re$/; $_ =~ /$re$re/; $_ =~ /$re.$re/;
В последнем случае точка будет означать не конкатенацию переменных, а метасимвол регулярного выражения.
После разделителя в команде qr/…/ могут стоять модификаторы. Сравните результаты:
$_='Ab'; my $re=qr/[a-z]+/; print $& if $_ =~ $re;
Печатается b
$_='Ab'; my $re=qr/[a-z]+/i; print $& if $_ =~ $re;
Печатается Ab
Поддерживаются все модификаторы кроме e, g и c. Применение модификатора o с оператором qr/…/ ведет к неприятному эффекту, который рассматривается в пункте 10.2.