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