是否有一种简单的方法来本地化(保留)所有"神奇变量",如$ 1,$等?

j_r*_*ker 9 perl

我知道,在Perl中的子程序,它保留了"默认变量"一个很好的想法$_local做任何事的,如果之前调用者正在使用它,例如:

sub f() {
    local $_;              # Ensure $_ is restored on dynamic scope exit
    while (<$somefile>) {  # Clobbers $_, but that's OK -- it will be restored
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,通常你$_首先使用的原因是因为你想使用正则表达式,这可能会将结果放在方便的"魔法"变量中$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
Run Code Online (Sandbox Code Playgroud)

但我发现真正令人惊讶的是,至少在我的ActivePerl 5.10.0中,评论出的local线仍然保留$1 - 也就是说,答案是"aXXa"!似乎支撑封闭块的词法(非动态)范围以某种方式保留了它的价值$1.

因此,我发现这种情况充其量令人困惑,并希望听到明确的解释.请注意,我实际上已经采取了一种防弹方式来保留所有正则表达式相关的魔术变量,而不必像以下那样枚举它们:

local @+, @-, $&, $1, $2, $3, $4, ...
Run Code Online (Sandbox Code Playgroud)

这显然是一个恶心的黑客.在那之前,我会担心我触摸的任何正则表达式都会破坏调用者不期望被破坏的东西.

谢谢!

yst*_*sth 8

也许你可以为文档提出更好的措辞.动态范围表示封闭块或子例程开始之前的所有内容,以及直到该块或子例程调用开始的所有内容等,不包括任何关闭的块.

另一种说法是:"当前活动动态范围中最后成功的子匹配"意味着local $x=$x;每个块的每个块的开头都隐含有一个.

大多数关于动态范围的提及(例如,http://perldoc.perl.org/perlglossary.html#scopehttp://perldoc.perl.org/perlglossary.html#dynamic-scoping)正在接近它其他方式.如果您认为成功的正则表达式隐式执行a local $1等,它们适用.

  • +1.`$ 1`等等是自动`local()`,范围令人困惑. (4认同)