要做到這一點,你需要使用模塊PadWalker,它可以讓你檢查存儲變量詞法墊。
use PadWalker qw/peek_my peek_our/;
sub debug {
my $my = peek_my 1;
my $our = peek_our 1;
my $caller = caller() . '::';
my $stash = do {
no strict 'refs';
\%$caller
};
my %lookup;
for my $pad ($my, $our) {
$lookup{$$pad{$_}} ||= $_ for keys %$pad;
}
for my $name (keys %$stash) {
if (ref \$$stash{$name} eq 'GLOB') {
for (['$' => 'SCALAR'],
['@' => 'ARRAY'],
['%' => 'HASH'],
['&' => 'CODE']) {
if (my $ref = *{$$stash{$name}}{$$_[1]}) {
$lookup{$ref} ||= $$_[0] . $caller . $name
}
}
}
}
for (@_) {
my $name = $lookup{\$_} || 'name not found';
print "$name: $_\n";
}
}
,然後使用它:
my $x = 5;
our $y = 10;
$main::z = 15;
debug $x, $y, $main::z;
它打印:
$x: 5
$y: 10
$main::z: 15
編輯:
這裏是相同的功能,重構一個位:
use PadWalker qw/peek_my peek_our/;
sub get_name_my {
my $pad = peek_my($_[0] + 1);
for (keys %$pad) {
return $_ if $$pad{$_} == \$_[1]
}
}
sub get_name_our {
my $pad = peek_our($_[0] + 1);
for (keys %$pad) {
return $_ if $$pad{$_} == \$_[1]
}
}
sub get_name_stash {
my $caller = caller($_[0]) . '::';
my $stash = do {
no strict 'refs';
\%$caller
};
my %lookup;
for my $name (keys %$stash) {
if (ref \$$stash{$name} eq 'GLOB') {
for (['$' => 'SCALAR'],
['@' => 'ARRAY'],
['%' => 'HASH'],
['&' => 'CODE']) {
if (my $ref = *{$$stash{$name}}{$$_[1]}) {
$lookup{$ref} ||= $$_[0] . $caller . $name
}
}
}
}
$lookup{\$_[1]}
}
sub get_name {
unshift @_, @_ == 2 ? 1 + shift : 1;
&get_name_my or
&get_name_our or
&get_name_stash
}
sub debug {
for (@_) {
my $name = get_name(1, $_) || 'name not found';
print "$name: $_\n";
}
}
爲什麼不使用Perl內置的調試工具,而不是重新發明輪子? – Cfreak 2011-03-04 22:17:56
我懷疑傑韋利::堆棧跟蹤將是一個更好的解決您的問題,那麼追捕變量名。 – Quentin 2011-03-04 22:18:33
爲什麼你不是Data :: Dumper的粉絲?如果我們確切地知道你的要求是什麼以及Data :: Dumper不滿足它們的要求,那麼回答你的問題將會更容易。沒有進一步的信息,我所能做的就是推薦Data :: Dumper,因爲這是我使用的。 – 2011-03-04 22:19:55