Как я могу перечислить все переменные, которые находятся в данной области? - PullRequest
31 голосов
/ 14 апреля 2009

Я знаю, что могу перечислить все пакетные и лексические переменные в заданной области, используя 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;
}

Ответы [ 4 ]

32 голосов
/ 14 апреля 2009

Вы можете получить доступ к таблице символов, проверить с. 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};
}
6 голосов
/ 14 апреля 2009

И это делает это. Спасибо 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;
}
5 голосов
/ 14 апреля 2009

Вы можете сделать что-то вроде следующего, чтобы проверить таблицу символов основного пакета:

{
    no scrict 'refs';

    for my $var (keys %{'main::'}) {
        print "$var\n";
    }
}
1 голос
/ 09 июля 2011

Спасибо, час, очень полезный код. Как примечание для будущих пользователей вашего кода с perl> 5.12:

Я использовал его в моем pdl2 .perldlrc, чтобы найти лексические переменные (например, команду 'y' в отладчике), и у меня было это предупреждение:

load_rcfile: загрузка

/ homes / pmg / .perldlrc определено (% хеш) устарело в (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" }

Чего я не понимаю, так это почему он жаловался только на определенный хеш, а не на массив?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...