Оператор 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
sub subr() { my $b=$_; print "\$b=$b\n"; if (/$b/) { print "Found $&\n" } else { print "Not found\n" } }
Выводится, как и положено,
$b=ab Found ab $b=cd Found cd
При первом обращении к подпрограме subr ее переменная $b имеет значение ab, при втором обращении она имеет значение cd. Пример без модификатора o работает так, как мы ожидали. Теперь поставим модификатор о к регулярному выражению:
$_='ab'; &subr(); $_='cd'; &subr();
sub subr() { my $b=$_; print "\$b=$b\n"; if (/$b/o) { print "Found $&\n" } else { print "Not found\n" } }
Печатается
$b=ab Found ab $b=cd Not found
Как говорится, что и требовалось доказать. Здесь дело даже не в том, что переменная $b объявлена в подпрограмме, она могла быть объявлена просто в каком-нибудь блоке, эффект был бы таким же:
$_='ab'; for my $i (0..1) { my $b=$_; print "\$b=$b\n"; if (/$b/) { print "Found $&\n" } else { print "Not found\n" } $_='cd'; }
Печатается
$b=ab Found ab $b=cd Found cd
А в случае с модификатором о:
$_='ab'; for my $i (0..1) { my $b=$_; print "\$b=$b\n"; if (/$b/o) { print "Found $&\n" } else { print "Not found\n" } $_='cd'; }
Печатается
$b=ab Found ab $b=cd Not found
Но если подобное регулярное выражение используется в подпрограмме многократно в цикле, то отсутствие модификатора о повлечет за собой многократную компиляцию этого регулярного выражения, хотя переменная $b внутри подпрограммы не меняет своего значения. Как тут быть? Эту проблему решают объекты регулярных выражений.
Объект регулярного выражения $re=qr/$b/ будет компилироваться каждый раз при входе в подпрограмму, но внутри цикла можно использовать этот объект многократно без перекомпиляции регулярного выражения:
$_='ab'; &subr(); $_='cd'; &subr();
sub subr() { my $b=$_; my $re=qr/$b/; print "\$b=$b\n"; if (/$re/) { print "Found $&\n" } else { print "Not found\n" } }
Печатает
$b=ab Found ab $b=cd Found cd
Forekc.ru
Рефераты, дипломы, курсовые, выпускные и квалификационные работы, диссертации, учебники, учебные пособия, лекции, методические пособия и рекомендации, программы и курсы обучения, публикации из профильных изданий