【问题标题】:How can I list all variables that are in a given scope?如何列出给定范围内的所有变量?
【发布时间】:2010-10-19 08:26:05
【问题描述】:

我知道我可以使用Padwalkerpeek_ourpeek_my 列出给定范围内的所有包变量和词法变量,但是如何获取所有全局变量的名称和值,例如@ 987654325@和$/?

#!/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;
}

【问题讨论】:

    标签: perl


    【解决方案1】:

    您可以访问符号表,请查看 p。 《Perl 编程》第 293 章 另请参阅“精通 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};
    }
    

    【讨论】:

    • %main:: 包含像“我们的 $foo”这样的包变量,而不是像 $/ 这样的全局变量。
    • 您可以使用内置的'ref'函数来获取符号的类型。
    • 你不需要严格的'refs';如果你说 %main::,你只有在说 %{'main::'} 时才需要它。
    • 这似乎是受版权保护的材料,如果没有在 brian d foy 的许可下发布,请删除链接。
    • 但是说真的,请阅读那一章,我相信它至少会为您尝试做的事情打下基础。
    【解决方案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;
    }
    

    【讨论】:

    • np,有时只需要朝着正确的方向前进。
    • 我得到“无法强制 GLOB 在 entersub 中进行字符串处理”...这个建议解决了这个问题:[apg.at.ufl.edu/wiki/….
    【解决方案3】:

    您可以执行以下操作来检查主包的符号表:

    {
        no strict 'refs';
    
        for my $var (keys %{'main::'}) {
            print "$var\n";
        }
    }
    

    【讨论】:

    • 哎呀,发帖时间太长了,MGoDave 先于我给出了答案。但是如果你使用 strict ,请确保不要包含 scrict 'refs',否则你会得到一个错误。
    • 实际上,事实证明这正是我编写我的代码的方式。您可以严格按照代码的方式进行操作(即键 %main:: 不带引号)
    • 你真的尝试过吗? %main:: 不包含全局变量,只包含在主包中声明的包变量。我正在寻找像 $/ 这样的全局变量。
    • 我试过了,它确实包含全局变量
    • 我收回了,我只是没认出他们,因为他们失去了他们的印记。嗯,如何判断它们是数组、散列还是标量。
    【解决方案4】:

    谢谢,Chas,非常有用的代码。 作为 perl > 5.12 代码的未来用户的说明:

    我在我的 pdl2 .perldlrc 中使用它来查找词法变量(如调试器中的 'y' 命令),我收到了以下警告:

    load_rcfile: 加载

    /homes/pmg/.perldlrc defined(%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" }
    

    我不明白的是为什么它只抱怨定义的哈希而不是数组?

    【讨论】:

    • 肯定有代码可以为数组打印类似的警告(参见 op.c 的第 7813 行左右),但perl -we '@a = defined @a' 似乎没有触发它,但perl -we '%h = (1,defined %h)' 肯定会触发警告。这闻起来像是某种形式的错误。
    • 有趣,你可以用这个perl -wE 'my @a;say defined @a ? @a : "f"'触发警告,但不能用这个perl -wE 'our @a;say defined @a ? @a : "f"'。这似乎是说只有实际的词法变量才会抛出警告。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-05
    相关资源
    最近更新 更多