13

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

perlopperlre似乎没有提到任何这样的限制。

例如:

 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";'
4

3 回答 3

10

文档证明localized 变量是这里的问题在perlvar5.14.0 中

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

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

请注意,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;
于 2012-06-06T06:54:22.907 回答
3

实际问题已经得到解答,所以这里是您如何完成任务的答案。

只需使用 eval 的返回值,而后者又使用 match 运算符的返回值。$1糟透了,避免。

use strict; use warnings;
$_ = "hello";
my @r = eval '/(.*)/';
# (
#     "hello"
# )
于 2012-06-06T09:05:49.637 回答
2

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

于 2012-06-06T06:34:33.930 回答