如果在eval中发生正则表达式匹配,则在外部环境中看不到与捕获相关的变量($ 1等)的更改.这是一个错误吗?
perlop和perlre似乎没有提到任何这样的限制.
例如:
use strict; use warnings;
$_ = "hello";
eval '/(.*)/';
print "GOT: $1\n";
Run Code Online (Sandbox Code Playgroud)
得到:
Use of uninitialized value $1 in concatenation (.) or string at -e line 1.
GOT:
Run Code Online (Sandbox Code Playgroud)
更简洁的演示是:
perl -we '$_="foo"; eval q(/(.*)/;) ; print "GOT:$1\n";'
Run Code Online (Sandbox Code Playgroud)
Lum*_*umi 10
文档证明了localized变量是这里的问题perlvar,见5.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: [...]
Run Code Online (Sandbox Code Playgroud)
该联机帮助页没有为所有这些特殊的全局变量(例如$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;
Run Code Online (Sandbox Code Playgroud)