2011-01-27 24 views
4

我在perl的关闭和$1 regexp变量中发现了一个可能的错误。简而言之,他们不会混在一起。perl关闭和正则表达式变量

让我们来看看这段代码。

use warnings; 

while ("1234567890"=~/(.)/sg) { 
    push @subs, sub{print $1;}; 
} 

for (@subs) {$_->()} 

你可以想象现在的perl将打印所有号码 - 相反,我得到了10个警告从不确定$1

这真的是一个错误,或者我错过了perl文档中的某些东西吗?是否有一些原因,为什么$1是未定义的并且不是关闭的一部分?

回答

7

我认为答案类似于perl closures and $_的答案。 $1也是一个全局变量。

你需要做的是:

my $x = $1; 
push @subs, sub{print $x;}; 
+0

哦,是的,这是有道理的:)但我认为你彪打印$ X。 – 2011-01-27 02:57:44

+0

谢谢,修复它(: – 2011-01-27 02:59:03

8

Perl有两个独立但大体兼容可变系统。符号表中的全局变量以及范围内的词法变量绑定词法板。

全局变量可以是符号解引用的目标,并且受动态范围影响,其范围为local。词汇变量(用my定义)可以关闭。

正则表达式匹配变量(以及所有Perl的其他特殊变量)是符号表中的全局变量,因此无法关闭它们。

为了解决这个问题,只是值复制到一个词:

use warnings; 

while ("1234567890"=~/(.)/sg) { 
    my $x = $1;    # creates a new lexical that the sub closes over 
    push @subs, sub{print $x;}; 
} 

for (@subs) {$_->()}