Опубликован: 18.06.2007 | Доступ: свободный | Студентов: 1354 / 35 | Оценка: 4.14 / 3.29 | Длительность: 12:44:00
ISBN: 978-5-94774-604-4
Лекция 9:

Встроенный код, переменные local и my

9.4. Встроенный код и директивы my и local

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

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

Для корректной работы переменных внутри встроенного кода их надо локализовать внутри регулярного выражения. Это делается директивой local. Значения таких переменных при возврате за встроенный код, в котором им присваивались значения, восстанавливаются такими, какими были до выполнения этого кода. Такие переменные должны быть глобальными, т.е. созданными не директивой my. Если в программе используется директива use strict, то глобальную переменную можно создать с помощью ключевого слова our. Тогда директива local внутри регулярного выражения делает из этой переменной как бы стек ее значений: при присваивании ей значения во встроенном коде оно наслаивается поверх предыдущего значения этой переменной, а при возврате назад восстанавливается предыдущее значение. После конца работы регулярного выражения эта переменная восстанавливает свое значение, которое имела перед входом в регулярное выражение.

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

#!/usr/bin/perl -w
use strict;

$_='ab';
our $o=1;
my $m=1;
/
(?: a  (?{ $o++; $m++ })  |
     ab (?{ print "\$o=$o, \$m=$m" })
)
           $
/x;

Регулярное выражение содержит конструкцию выбора:

/(a|ab)$/

Вначале будет найден символ a и выберется первая ветка условного шаблона, при этом переменные $o и $m увеличатся на единицу. Но затем этот выбор будет отменен, поскольку за символом a должен идти символ b, и управление получит вторая альтернатива конструкции выбора, в которой будут распечатаны значения переменных $o и $m. На печать выйдет:

$o=2, $m=2

В этом примере различия в работе этих переменных нет. Теперь локализуем глобальную переменную $o в регулярном выражении:

#!/usr/bin/perl -w
use strict;

$_='ab';
our $o=1;
my $m=1;
/  (?{ local $o })
   (?: a  (?{ $o++; $m++ })|
       ab (?{ print "\$o=$o, \$m=$m" })
   )
 $
/x;

На сей раз напечатается это:

$o=1, $m=2

Этот пример показывает работу директивы local во встроенном коде.

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

Если объявить переменную my внутри регулярного выражения, то в других блоках встроенного кода переменная с этим именем не будет соответствовать той переменной, что была объявлена. Она либо будет создана заново как глобальная, либо, если переменная с этим именем уже существует до регулярного выражения, она будет отождествлена с ней. При возврате такая переменная не будет восстанавливать свои старые значения. Вот два примера:

$_='ab';
our $o=1;
/  (?{ my $m=10; local $o })
   (?: a  (?{ $o++; $m++ })|
       ab (?{ print "\$o=$o, \$m=$m" })
   )
 $
/x;

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

$o=1, $m=1

Мы видим, что во втором встроенном коде переменная $m создалась заново с неопределенным значением, затем к нему применили ++ и получили 1. И это значение потом использовалось при печати.

$_='ab';
our $o=1;
my $m=10;
/  (?{ my $m=5; local $o })
   (?: a  (?{ $o++; $m++ })|
       ab (?{ print "\$o=$o, \$m=$m" })
   )
 $
/x;

Здесь напечатается

$o=1, $m=11

Во втором и третьем встроенном коде использовалась переменная $m, которая была создана до регулярного выражения.

Директиву local можно комбинировать с присваиванием значения этой переменной.

Например:

local ($ctop) = $ctop+1;
Константин Бражников
Константин Бражников
Россия
Mike .
Mike .
Россия