Technical question:
Given a regex:
my $regEx = qr{whatever$myVar}oxi; # Notice /o for "compile-once"
What is the most effective way to force it to recompile on demand? (e.g. when I know from the program logic that $myVar
value changed) without dropping /o
and depending on Perl's internal smarts to auto-recompile?
NOTE: The regex is used in a substitution, which may affect re-compilation rules sans /o:
$string2 =~ s/$regEx//;
The context is:
I have a regular expression that is built by slurping in a fairly long (>1k long) string from a config file.
That file is re-read once every 60 minutes.
If the string read from the file changes (as defined by changing file timestamp), I want to re-compile the regex using the re-slurped string value in $myVar
.
The regex is used repeatedly and frequently in the Perl module running under mod_perl.
This means that (coupled with the string being >1-2k long) I must use "/o
" modifier to force compile-once on the regex, to avoid performance hit of Perl repeatedly checking if the variable value changed (this heuristic is from perlop qr//
, since the regex is used as part of s///
as shown above and not by itself as a match).
That in turn means that, when I know that the variable changed after re-slurping it in 1 hour, I need to force the regex to re-compile despite the /o
modifier.
UPDATE: Here's an illustration of why I need /o
- without it, the regex is recompiled (and thus necessarily checked) every loop iteration; with it it is NOT:
$ perl -e '{for (my $i=0; $i<3; $i++) {
my $re = qr{$i}oix; $s="123"; $s =~ s/$re//;
print "i=$i; s=$s\n"; }}'
i=0; s=123
i=1; s=123
i=2; s=123
$ perl -e '{ for (my $i=0; $i<3; $i++) {
my $re = qr{$i}ix; $s="123"; $s =~ s/$re//;
print "i=$i; s=$s\n"; }}'
i=0; s=123
i=1; s=23
i=2; s=13
when I know from the program logic that $myVar value changed
m//
, s///
and qr//
only compile if the pattern doesn't change. All you have to do to get the behaviour you requested is to remove the /o
.
$ perl -Mre=debug -e'
qr/$_/ for qw( abc abc def def abc abc );
' 2>&1 | grep Compiling
Compiling REx "abc"
Compiling REx "def"
Compiling REx "abc"
Therefore,
If the string read from the file changes (as defined by changing file timestamp), I want to re-compile the regex using the re-slurped string value in $myVar.
my $new_myVar = ...;
if ($myVar ne $new_myVar) {
$re = qr/$new_myVar/;
$myVar = $new_myVar;
}
...
s/$re/.../
or just
$myVar = ...;
...
s/$myVar/.../