Как я могу перечислить все переменные, которые находятся в заданной области?
Я знаю, что могу перечислять все пакетные и лексические переменные в заданной области, используя Padwalker
peek_our
и peek_my
, но как я могу получить имена и значения всех глобальных переменных, таких как $"
и $/
?
#!/usr/bin/perl
use strict;
use warnings;
use PadWalker qw/peek_our peek_my/;
use Data::Dumper;
our $foo = 1;
our $bar = 2;
{
my $foo = 3;
print Dumper in_scope_variables();
}
print Dumper in_scope_variables();
sub in_scope_variables {
my %in_scope = %{peek_our(1)};
my $lexical = peek_my(1);
#lexicals hide package variables
while (my ($var, $ref) = each %$lexical) {
$in_scope{$var} = $ref;
}
##############################################
#FIXME: need to add globals to %in_scope here#
##############################################
return \%in_scope;
}
Ответы
Ответ 1
Вы можете получить доступ к таблице символов, проверьте p. 293 из "Программирование Perl"
Также смотрите "Освоение Perl: http://www252.pair.com/comdog/mastering_perl/
В частности: http://www252.pair.com/comdog/mastering_perl/Chapters/08.symbol_tables.html
Те переменные, которые вы ищете, будут находиться под основным пространством имен
Быстрый поиск в Google дал мне:
{
no strict 'refs';
foreach my $entry ( keys %main:: )
{
print "$entry\n";
}
}
Вы также можете сделать
*sym = $main::{"/"}
а также для других значений
Если вы хотите найти тип символа, который вы можете сделать (от мастеринга perl):
foreach my $entry ( keys %main:: )
{
print "-" x 30, "Name: $entry\n";
print "\tscalar is defined\n" if defined ${$entry};
print "\tarray is defined\n" if defined @{$entry};
print "\thash is defined\n" if defined %{$entry};
print "\tsub is defined\n" if defined &{$entry};
}
Ответ 2
И это все. Благодаря MGoDave и kbosak за то, что я дал ответ перед моим лицом, я был слишком глуп, чтобы видеть (я посмотрел в% main:: для начала, но пропустил, что у них не было их сигил). Вот полный код:
#!/usr/bin/perl
use strict;
use warnings;
use PadWalker qw/peek_our peek_my/;
use Data::Dumper;
our $foo = 1;
our $bar = 2;
{
my $foo = 3;
print Dumper in_scope_variables();
}
print Dumper in_scope_variables();
sub in_scope_variables {
my %in_scope = %{peek_our(1)};
my $lexical = peek_my(1);
for my $name (keys %main::) {
my $glob = $main::{$name};
if (defined ${$glob}) {
$in_scope{'$' . $name} = ${$glob};
}
if (defined @{$glob}) {
$in_scope{'@' . $name} = [@{$glob}];
}
if (defined %{$glob}) {
$in_scope{'%' . $name} = {%{$glob}};
}
}
#lexicals hide package variables
while (my ($var, $ref) = each %$lexical) {
$in_scope{$var} = $ref;
}
return \%in_scope;
}
Ответ 3
Для проверки таблицы символов основного пакета вы можете сделать что-то вроде следующего:
{
no scrict 'refs';
for my $var (keys %{'main::'}) {
print "$var\n";
}
}
Ответ 4
Спасибо, Час, очень полезный код.
В качестве примечания для будущих пользователей вашего кода с perl > 5.12:
Я использовал его в моем pdl2.perldlrc, чтобы узнать лексические переменные (например, команда "y" в отладчике), и я получил это предупреждение:
load_rcfile: загрузка
/homes/pmg/.perldlrc определен (% hash) устарел на строку (eval 254) 36.
(Maybe you should just omit the defined()?)
От perldoc -f определяется
Использование определенных для агрегатов (хешей и массивы) устарела. Он имел обыкновение сообщите, память для этого совокупность когда-либо была выделена. Такое поведение может исчезнуть в будущем версии Perl. Вы должны вместо этого используйте простой тест для размера:
> if (@an_array) { print "has array elements\n" }
> if (%a_hash) { print "has hash members\n" }
Я не понимаю, почему он только жаловался на определенный хеш, а не на массив?