我知道在Perl的一个子例程中,在使用它之前保留“默认变量”$_
与local
是一个非常好的主意,以防调用者使用它,例如:
sub f() {
local $_; # Ensure $_ is restored on dynamic scope exit
while (<$somefile>) { # Clobbers $_, but that's OK -- it will be restored
...
}
}
现在,您通常首先使用$_
的原因是因为您想要使用正则表达式,这可能会将结果放入方便的“神奇”变量,如$1
,$2
等。我也想保留这些变量,但我还没有找到办法做到这一点。
所有perlvar都说@+
和@-
,$1
等似乎在内部依赖,指的是“当前活动动态范围中最后成功的子匹配”。但即使这似乎与我的实验不一致。根据经验,以下代码按照我的希望打印“aXaa”:
$_ = '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
但我发现真正令人惊讶的是,至少在我的ActivePerl 5.10.0中,评论local
行仍然保留$1
- 也就是说,回答“aXXa”正在制作中!似乎括号内的块的词法(非动态)范围以某种方式保留$1
的值。
因此,我发现这种情况充其量令人困惑,并希望听到明确的解释。请注意,我实际上已经采取了一种防弹措施来保存所有正则表达式相关的魔术变量,而不必像以下那样枚举它们:
local @+, @-, $&, $1, $2, $3, $4, ...
这显然是一个恶心的黑客。在那之前,我会担心我触摸的任何正则表达式都会破坏调用者不期待被破坏的东西。
谢谢!
答案 0 :(得分:8)
也许您可以为文档提出更好的措辞。动态范围表示封闭块或子例程开始之前的所有内容,以及该块或子例程调用开始之前的所有内容。除之外的任何已关闭块都被排除。
另一种说法是:“当前活动动态范围中的最后成功子匹配”意味着每个块的每个块的开头都隐含local $x=$x;
。
大多数动态范围提及(例如,http://perldoc.perl.org/perlglossary.html#scope或http://perldoc.perl.org/perlglossary.html#dynamic-scoping)
从相反的方向接近它。如果您认为成功,它们适用
正则表达式隐含地执行local $1
等等。
答案 1 :(得分:3)
我不确定是否有任何真正的理由成为所有这些变量的偏执狂。我已经设法使用Perl将近十年而不需要在此上下文中使用显式local
。
您的具体问题的答案是:数字变量的数量不是给定的(即使您可以使用多少匹配的硬内存限制)。因此,无法同时对所有这些进行本地化。
答案 2 :(得分:1)
我觉得你太担心了。最好的办法是运行你的匹配运算符,立即将你想要的值保存到有意义的变量中,然后让特殊变量做他们做的任何事情而不用担心它们:
if( $string =~ m/...(a.c).../ ) {
my $found = $1;
}
当我想捕获字符串的一部分时,我经常使用列表上下文中的匹配运算符来获取回忆的列表:
my @array = $string =~ m/..../g;