Регулярные выражения Perl и их применение
ba2f5a3f

Автоматическая локализация специальных переменных, относящихся к регулярным выражениям


Теперь рассмотрим такой пример:

my $a=1; $_='a'; /(a)/; print "$1\n"; /(b)/; print "$1\n";

Будет напечатано

a a

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

Теперь рассмотрим более интересный пример:

my $a=1; $_='ab'; /(a)/; print "$1\n"; if ($a) { /(b)/; print "$1\n"; } print "$1\n";

Будет напечатано

a b a

Во внешнем регулярном выражении переменная $1 получает значение a, в регулярном выражении внутри блока эта переменная получает значение b. Затем при выходе из блока мы пытаемся использовать это последнее присвоенное значение. И тут нас поджидает сюрприз (не знаю, приятный или нет): вне блока переменная $1 опять имеет свое старое значение. Это может породить труднонаходимые ошибки в программе, если не позаботиться о сохранении необходимых специальных переменных в переменных my.

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

$_='ab'; /(a)/; print "$1\n"; &subr(); print "$1\n";

sub subr() { /(b)/; print "$1\n"; }

Напечатается

a b a

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



Содержание раздела