Perl:为什么eval'/(...)/'设置$ 1?

时间:2012-06-06 06:24:31

标签: regex perl eval

如果在eval中发生正则表达式匹配,则在外部环境中看不到对捕获相关变量($ 1等)的更改。这是一个错误吗?

perlop perlre 似乎没有提及任何此类限制。

例如:

 use strict; use warnings;
 $_ = "hello";
 eval '/(.*)/';
 print "GOT: $1\n";

给出:

Use of uninitialized value $1 in concatenation (.) or string at -e line 1.
GOT:

更简洁的演示是:

perl -we '$_="foo"; eval q(/(.*)/;) ; print "GOT:$1\n";'

3 个答案:

答案 0 :(得分:10)

local ized变量问题的文档证明位于perlvar of 5.14.0

  

除非另有说明,否则这些变量是只读的和动态范围的。

     

正则表达式变量的动态特性意味着它们的值仅限于它们所处的块[...]

请注意,这些文档是absent from the 5.12.4 perldoc


问题是local变量。我的perldoc -f eval (5.12.4)副本有这样的说法:

The assignment to $@ occurs before restoration of localised
variables, which means a temporary is required if you want to
mask some but not all errors: [...]

联机帮助页没有为所有这些特殊的全局变量(如$1$&以及其他可能的其他变量)做出明确的声明,但是块定位和后续恢复就是这里发生的事情。

将变量分配到eval内部,并在剩下eval块后恢复原始值。

use strict; use warnings;
use Test::More;
use constant V => 'hello';

$_ = V;

note '*** block eval';
eval {
        is $_, V, 'input ok';
        /(.*)/;
        is $&, V, 'in eval'; is $1, V, 'in eval';
};
is $&, V, 'after eval'; is $1, V, 'after eval';

note '*** without eval';
is $_, V, 'input ok';
/(.*)/;
is $&, V; is $1, V;

done_testing;

答案 1 :(得分:3)

实际问题已经回答了,所以这就是你如何完成任务的答案。

只需使用eval的返回值,而eval又使用匹配运算符的返回值。 $1很糟糕,避免。

use strict; use warnings;
$_ = "hello";
my @r = eval '/(.*)/';
# (
#     "hello"
# )

答案 2 :(得分:2)

在eval结束后,eval中声明的任何词法变量都将丢失。