ちなみにこれ、皆はまるところなので昨日の続き:



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/;
}
}