让 Perl 打印完整的“关键路径"到值(Data::Dumper 不会) [英] Get Perl to print full "key path" to values (Data::Dumper won't)

查看:54
本文介绍了让 Perl 打印完整的“关键路径"到值(Data::Dumper 不会)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

$foo{alongkeyname}{anotherlongkeyname}{yetanotherlongkeyname}{afairlyshortkeynamewellitgotlongwhileiwastypingitsoiguessnot}{bob}{something} = 1;

如何让 Perl 打印 $foo 并向我显示完整的路径名"到 1?换句话说,我希望输出看起来类似于上面输入.

Data::Dumper 不会这样做,并且长键名包装输出,甚至缩进的形式也不太有用.

很久以前,我在 https 上编写了自己的展开"子例程://github.com/barrycarter/bcapps/blob/master/bclib.pl#L109 输出:

<键>沿键名</key><val><hash HASH(0x95103b4)><键>另一个长键名</key><val><hash HASH(0x9510464)><键>又一个长键名</key><val><hash HASH(0x9510434)><键>相当短的keynamewellitgotlongwhileiwastypingitsoiguessnot</key><val><hash HASH(0x95bae7c)><键>鲍勃</key><val><hash HASH(0x95cf8bc)>东西:1</hash HASH(0x95cf8bc)></val></hash HASH(0x95bae7c)></val></hash HASH(0x9510434)></val></hash HASH(0x9510464)></val></hash HASH(0x95103b4)></val></hash HASH(0x92a33a4)>

但这也不是很有用.

启发这个问题的现实项目:从 SYNOP/BUOY 数据中提取XML::metaf2xml 的简单散列输出

谢谢本!我试过这个,它在我的例子中效果很好.然后我在另一个哈希上试了一下,得到:

$VAR1 = {'remark' =>[{'obsStationType' =>{'stationType' =>{'v' =>'AO2'},'s' =>'AO2'}},{'needMaint' =>{'s' =>'$'}}],'QNH' =>{'inHg' =>{'v' =>'29.99'},'s' =>'A2999'},'visPrev' =>{'距离' =>{'u' =>'SM','v' =>'7','rp' =>'1'},'s' =>'7SM'},'sfcWind' =>{'风' =>{'速度' =>{'u' =>'KT','v' =>'3'},'dir' =>{'rn' =>'5','v' =>'60','rp' =>'4'}},'measurePeriod' =>{'u' =>'MIN','v' =>'2'},'s' =>'06003KT'},'obsStationId' =>{'id' =>{'v' =>'KBTR'},'s' =>'KBTR'},'obsTime' =>{'s' =>'080940Z','timeAt' =>{'小时' =>{'v' =>'09'},'分钟' =>{'v' =>'40'},'天' =>{'v' =>'08'}}},'s' =>'KBTR 080940Z 06003KT 7SM SCT003 BKN200 24/23 A2999 RMK AO2 $','云' =>[{'cloudCover' =>{'v' =>'SCT'},'s' =>'SCT003','cloudBase' =>{'u' =>'FT','v' =>'300'}},{'cloudCover' =>{'v' =>'BKN'},'s' =>'BKN200','cloudBase' =>{'u' =>'FT','v' =>'20000'}}],'温度' =>{'relHumid4' =>{'v' =>'94.15'},'露点' =>{'温度' =>{'u' =>'C','v' =>'23'}},'relHumid3' =>{'v' =>'94.03'},'relHumid1' =>{'v' =>'94.16'},'relHumid2' =>{'v' =>'94.17'},'空气' =>{'温度' =>{'u' =>'C','v' =>'24'}},'s' =>'24/23'}};

所以我想我想回答的问题是:这个散列的什么值会给我你在上面看到的94.15"?从上面很难判断.

(如果有人好奇,答案是 $hash{temperature}{relHumid4}{v})

更多谢谢,伊尔马里.我在上面尝试了 dump_var($VAR1) w/我的 VAR1 并得到...

<预><代码>哈希(0x9ae6764)= undef;

我也尝试了 dump_var({$VAR1}) ,结果相同.我可能错过了什么.你能把我的 VAR1 剪切并粘贴到上面看看它是否有效吗?正如您在使用"声明中指出的那样,我确实导出了倾销者".

解决方案

这是一个快速的自助解决方案:

use Data::Dumper 'Dumper';子转储变量{我的 ($prefix, $var) = @_;我的@rv;本地 $Data::Dumper::Indent = 0;本地 $Data::Dumper::Terse = 1;if (ref $var eq 'ARRAY' 和 @$var) {对于我的 $i (0 .. $#$var) {push @rv, dump_var($prefix . "->[$i]", $var->[$i]);}} elsif (ref $var eq 'HASH' 和 %$var) {foreach 我的 $key(排序键 %$var){push @rv, dump_var($prefix . '->{'.Dumper($key).'}', $var->{$key});}} elsif (ref $var eq 'SCALAR') {push @rv, dump_var('${' . $prefix . '}', $$var);} 别的 {推@rv, "$prefix = ".倾销者($var) .";\n";}返回@rv;}

和一些测试代码:

我的 $foo = {阿尔法=>['测试版',\'伽玛'],一 =>{ 两个 =>{ 三 =>3、四个=>3.141 },五 =>{ 六 =>undef, 七 =>\*标准输入 },},foob​​ar =>sub { print "Hello, world!\n";},};打印 dump_var('$foo' => $foo);

产生输出:

$foo->{'alpha'}->[0] = 'beta';${$foo->{'alpha'}->[1]} = 'gamma';$foo->{'foobar'} = sub { "DUMMY" };$foo->{'one'}->{'five'}->{'seven'} = \*::STDIN;$foo->{'one'}->{'five'}->{'six'} = undef;$foo->{'one'}->{'two'}->{'four'} = '3.141';$foo->{'one'}->{'two'}->{'three'} = 3;

测试时这段代码的 PHP 版本,我意识到它没有正确处理空数组和散列.我已经修复了代码,以便将这些值直接传递给 Dumper.

$foo{alongkeyname}{anotherlongkeyname}{yetanotherlongkeyname}{afairlyshortkeynamewellitgotlongwhileiwastypingitsoiguessnot}{bob}{something} = 1; 

How do I get Perl to print $foo and show me the full "path name" to get to 1? In other words, I want output that looks similar to the input above.

Data::Dumper won't do this, and the long key names wrap the output, making even the indented form less useful.

Ages ago, I wrote my own "unfold" subroutine at https://github.com/barrycarter/bcapps/blob/master/bclib.pl#L109 which outputs:

<hash HASH(0x92a33a4)> 
<key> 
alongkeyname 
</key> 
<val> 
<hash HASH(0x95103b4)> 
<key> 
anotherlongkeyname 
</key> 
<val> 
<hash HASH(0x9510464)> 
<key> 
yetanotherlongkeyname 
</key> 
<val> 
<hash HASH(0x9510434)> 
<key> 
afairlyshortkeynamewellitgotlongwhileiwastypingitsoiguessnot 
</key> 
<val> 
<hash HASH(0x95bae7c)> 
<key> 
bob 
</key> 
<val> 
<hash HASH(0x95cf8bc)> 
something: 1 
</hash HASH(0x95cf8bc)> 

</val> 
</hash HASH(0x95bae7c)> 

</val> 
</hash HASH(0x9510434)> 

</val> 
</hash HASH(0x9510464)> 

</val> 
</hash HASH(0x95103b4)> 

</val> 
</hash HASH(0x92a33a4)> 

but that's not really useful either.

Real-life project inspiring this question: pulling SYNOP/BUOY data from the XML::Simple hashified output of metaf2xml

EDIT: Thank you Ben! I tried this and it worked great on my example. Then I tried it on another hash, and got:

$VAR1 = {'remark' => [{'obsStationType' => {'stationType' => {'v' => 'AO2'},'s' => 'AO2'}},{'needMaint' => {'s' => '$'}}],'QNH' => {'inHg' => {'v' => '29.99'},'s' => 'A2999'},'visPrev' => {'distance' => {'u' => 'SM','v' => '7','rp' => '1'},'s' => '7SM'},'sfcWind' => {'wind' => {'speed' => {'u' => 'KT','v' => '3'},'dir' => {'rn' => '5','v' => '60','rp' => '4'}},'measurePeriod' => {'u' => 'MIN','v' => '2'},'s' => '06003KT'},'obsStationId' => {'id' => {'v' => 'KBTR'},'s' => 'KBTR'},'obsTime' => {'s' => '080940Z','timeAt' => {'hour' => {'v' => '09'},'minute' => {'v' => '40'},'day' => {'v' => '08'}}},'s' => 'KBTR 080940Z 06003KT 7SM SCT003 BKN200 24/23 A2999 RMK AO2 $','cloud' => [{'cloudCover' => {'v' => 'SCT'},'s' => 'SCT003','cloudBase' => {'u' => 'FT','v' => '300'}},{'cloudCover' => {'v' => 'BKN'},'s' => 'BKN200','cloudBase' => {'u' => 'FT','v' => '20000'}}],'temperature' => {'relHumid4' => {'v' => '94.15'},'dewpoint' => {'temp' => {'u' => 'C','v' => '23'}},'relHumid3' => {'v' => '94.03'},'relHumid1' => {'v' => '94.16'},'relHumid2' => {'v' => '94.17'},'air' => {'temp' => {'u' => 'C','v' => '24'}},'s' => '24/23'}};

So the question I think I want to answer is: what value of this hash will give me the "94.15" you see above? It's sort of hard to tell from the above.

(If anyone's curious, the answer is $hash{temperature}{relHumid4}{v})

MORE EDIT: Thanks, Ilmari. I tried dump_var($VAR1) w/ my VAR1 above and got...


HASH(0x9ae6764) = undef;

I also tried dump_var({$VAR1}) with the same result. I might've missed something. Could you cut and paste my VAR1 above and see if it works? I did export 'Dumper' as you indicate in your 'use' statement.

解决方案

Here's a quick do-it-yourself solution:

use Data::Dumper 'Dumper';

sub dump_var {
    my ($prefix, $var) = @_;
    my @rv;
    local $Data::Dumper::Indent = 0;
    local $Data::Dumper::Terse = 1;
    if (ref $var eq 'ARRAY' and @$var) {
        for my $i (0 .. $#$var) {
            push @rv, dump_var($prefix . "->[$i]", $var->[$i]);
        }
    } elsif (ref $var eq 'HASH' and %$var) {
        foreach my $key (sort keys %$var) {
            push @rv, dump_var($prefix . '->{'.Dumper($key).'}', $var->{$key});
        }
    } elsif (ref $var eq 'SCALAR') {
        push @rv, dump_var('${' . $prefix . '}', $$var);
    } else {
        push @rv, "$prefix = " . Dumper($var) . ";\n";
    }
    return @rv;
}

and some test code:

my $foo = {
    alpha => [ 'beta', \ 'gamma' ],
    one => { two => { three => 3, four => 3.141 },
             five => { six => undef, seven => \*STDIN },
    },
    foobar => sub { print "Hello, world!\n"; },
};

print dump_var('$foo' => $foo);

which produces the output:

$foo->{'alpha'}->[0] = 'beta';
${$foo->{'alpha'}->[1]} = 'gamma';
$foo->{'foobar'} = sub { "DUMMY" };
$foo->{'one'}->{'five'}->{'seven'} = \*::STDIN;
$foo->{'one'}->{'five'}->{'six'} = undef;
$foo->{'one'}->{'two'}->{'four'} = '3.141';
$foo->{'one'}->{'two'}->{'three'} = 3;

Edit: While testing a PHP version of this code, I realized that it didn't correctly handle empty arrays and hashes. I've fixed the code so that such values are passed directly to Dumper.

这篇关于让 Perl 打印完整的“关键路径"到值(Data::Dumper 不会)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆