I know that in a subroutine in Perl, it's a very good idea to preserve the "default variable" $_
with local
before doing anything with it, in case the caller is using it, e.g.:
sub f() {
local $_; # Ensure $_ is restored on dynamic scope exit
while (<$somefile>) { # Clobbers $_, but that's OK -- it will be restored
...
}
}
Now, often the reason you use $_
in the first place is because you want to use regexes, which may put results in handy "magic" variables like $1
, $2
etc. I'd like to preserve those variables too, but I haven't been able to find a way to do that.
All perlvar says is that @+
and @-
, which $1
etc. seem to depend on internally, refer to the "last successful submatches in the currently active dynamic scope". But even that seems at odds with my experiments. Empirically, the following code prints "aXaa" as I had hoped:
$_ = 'a';
/(.)/; # Sets $1 to 'a'
print $1; # Prints 'a'
{
local $_; # Preserve $_
$_ = 'X';
/(.)/; # Sets $1 to 'X'
print $1; # Prints 'X'
}
print $_; # Prints 'a' ('local' restored the earlier value of $_)
print $1; # Prints 'a', suggesting localising $_ does localise $1 etc. too
But what I find truly surprising is that, in my ActivePerl 5.10.0 at least, commenting out the local
line still preserves $1
-- that is, the answer "aXXa" is produced! It appears that the lexical (not dynamic) scope of the brace-enclosed block is somehow preserving the value of $1
.
So I find this situation confusing at best and would love to hear a definitive explanation. Mind you, I'd actually settle for a bulletproof way to preserve all regex-related magic variables without having to enumerate them all as in:
local @+, @-, $&, $1, $2, $3, $4, ...
which is clearly a disgusting hack. Until then, I will worry that any regex I touch will clobber something the caller was not expecting to be clobbered.
Thanks!