eval中声明的任何词汇变量在eval结束后都会丢失。要捕获和隔离在eval中设置的全局变量,可以使用Safe模块来创建新的全局名称空间。像下面这样:
use Safe;
my $vars = Safe->new->reval(qq{
$code_to_eval;
$code_to_search_the_symbol_table_for_declared_variables
});
,其中搜索码被定义为东西,走在嵌套%main::
符号表中寻找感兴趣的任何变量。你可以让它返回一个包含这些信息的数据结构,然后你可以用它来做你喜欢的事情。
如果你只担心在根级别定义的变量,你可以写这样的:
use strict;
use warnings;
my $eval_code = '$foo=42; $bar=3.14;';
use Safe;
my $vars = Safe->new->reval(
$eval_code . q{;
my %vars;
for my $name (keys %main::) {
next if $name =~ /::$/ # exclude packages
or not $name =~ /[a-z]/; # and names without lc letters
my $glob = $main::{$name};
for (qw($SCALAR @ARRAY %HASH)) {
my ($sigil, $type) = /(.)(.+)/;
if (my $ref = *$glob{$type}) {
$vars{$sigil.$name} = /\$/ ? $$ref : $ref
}
}
}
\%vars
});
print "$_: $$vars{$_}\n" for keys %$vars;
# $foo: 42
# $bar: 3.14
搜索代码还可以采用Padwalker搜索当前词法范围使用peek_my
任何定义的变量功能。
并开始Perl的什么版本允许从字符串访问水珠插槽后?我可以发誓,我曾经得到一个“不是散列”的错误,试图做这样的事情。所以,我想我在一些增量页面上一定错过了。 – Axeman