ちなみにこれ、皆はまるところなので昨日の続き:
sub match_me
{
my ($regexp, $string) = @_;
return $string =~ /$regexp/o;
}
これは一見速くなりそうだけど、実はNG。/oを使うと、最初に$regexpに渡した値でこの正規表現はコンパイルされてしまうので、次に違う値を$regexpに渡しても前回の正規表現を使用してしまう。以下テスト:
use strict;
sub poop { my($regexp, $string) = @_ ; return $string =~ /$regexp/o };
my $RE1 = "foo";
my $RE2 = "bar";
my $STRING1 = "foo" x 2;
my $STRING2 = "bar" x 2;
if (poop($RE1, $STRING1)) {
print "$RE1 matches $STRING1\n";
}
if (poop($RE2, $STRING1)) {
print "$RE2 matches $STRING1\n";
}
if (poop($RE1, $STRING2)) {
print "$RE1 matches $STRING2\n";
}
if (poop($RE2, $STRING2)) {
print "$RE2 matches $STRING2\n";
}
daisuke@beefcake daisuke$ perl poop.pl
foo matches foofoo
bar matches foofoo
本当は最初のと最後のがあたるはずなのに、最初の二つしかあたらない。これはどういうことかというと、/oが$regexpをコンパイルするのは最初のpoop()呼び出しの時だけだから。だからこうやって動的に正規表現を作成して使用する場合には/oは使っちゃ駄目駄目。
例えばpoop()の中で繰り返し同じ同じ正規表現を使う場合はqr()を使うと吉:
sub poop {
my($regexp, $string) = @_;
my $compiled = qr($regexp);
for (1..10) {
$string =~ /$compiled/;
}
}
コメント