如果在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";'
答案 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中声明的任何词法变量都将丢失。