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

Построение эффективных регулярных выражений. Оператор qr/…/ и объекты регулярных выражений.

< Лекция 9 || Лекция 10: 123456 || Лекция 11 >

10.2 Оператор qr/…/ и проблемы при использовании модификатора o

Когда в операторе qr/…/ используется модификатор o и есть интерполируемые переменные, этот объект регулярного выражения больше не модифицируется, если ему даже присваивается значение. Т.е. он как бы привязан к действующим на момент первого выполнения значениям интерполируемых переменных. Поэтому не используйте модификатор o с объектами регулярных выражений, если не хотите труднонаходимых сюрпризов. Такой пример:

my $a=$_='ab';
my $re=qr"$a"o;
for my $i (0..1)
 { print "$re\n";
   print "Found $&\n" if /$re/;
   $_=$a='cd';
   $re=qr"$a";
 }

За циклом мы создаем объект регулярного выражения $re с интерполяцией переменной $a. В цикле перед вторым проходом переменная $a меняет значение, и после этого опять повторяется оператор $re=qr"$a". На печать выходят оба найденных значения:

(?-xism:ab)
Found ab
(?-xism:cd)
Found cd

Теперь внесем первый оператор my $re=qr"$a"o в цикл:

my $a=$_='ab';
for my $i (0..1)
 { my $re=qr"$a"o;
   print "$re\n";
   print "Found $&\n" if /$re/;
   $_=$a='cd';
   $re=qr"$a";
 }

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

(?-xism:ab)
Found ab
(?-xism:ab)

Мы видим следующее: хотя переменная $a поменяла свое значение на cd, объект регулярного выражения $re стал как бы константой и продолжает хранить старое ее значение $a='ab', несмотря на то, что мы присваиваем $re новое значение. Виной этому модификатор o. Без него пример работает так, как ожидается:

my $a=$_='ab';
for my $i (0..1)
 { my $re=qr"$a";
   print "$re\n";
   print "Found $&\n" if /$re/;
   $_=$a='cd';
   $re=qr"$a";
 }

И печатает, как и в первом случае,

(?-xism:ab)
Found ab
(?-xism:cd)
Found cd

Если интерполируемых переменных нет, то опять все работает так, как ожидается:

my $a=$_='ab';
my $re=qr"ab"o;
for my $i (0..1)
 { print "$re\n";
   print "Found $&\n" if /$re/;
   $_=$a='cd';
   $re=qr"cd";
 }

Выводит

(?-xism:ab)
Found ab
(?-xism:cd)
Found cd
< Лекция 9 || Лекция 10: 123456 || Лекция 11 >
Константин Бражников
Константин Бражников
Россия
Mike .
Mike .
Россия