$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' => '2开发者_C百科4'}},'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
.
Data::Dumper can print output similar to what you're looking for by setting Indent to 0.
[ben@imac ~]$ perl
use Data::Dumper;
$Data::Dumper::Indent = 0;
$foo{alongkeyname}{anotherlongkeyname}{yetanotherlongkeyname}{afairlyshortkeynamewellitgotlongwhileiwastypingitsoiguessnot}{bob}{something} = 1;
print Dumper(\%foo);
Output:
$VAR1 = {'alongkeyname' => {'anotherlongkeyname' => {'yetanotherlongkeyname' => {'afairlyshortkeynamewellitgotlongwhileiwastypingitsoiguessnot' => {'bob' => {'something' => 1}}}}}};
For a possible solution to the problem behind your question, please see the feature announced today in the Project News for metaf2xml.
精彩评论