我有来自Unix命令的行,但每行都有可变数量的字段 我想创建嵌套哈希。我怎样才能做到这一点。
我使用split ('[\|=]' $line)
命令数据:
node:server1|name=server1
node:server1|status=up
node:server1|state=running
node:server1|initial_incarnation=1
node:server1|os_status=up
node:server1|summary=ok
node:server2|subnet:X.Y.Z.0|name=X.Y.Z.0
node:server2|subnet:X.Y.Z.0|route_id=1
node:server2|subnet:X.Y.Z.0|status=up
node:server2|subnet:X.Y.Z.0|ip_monitor=off
node:server1|interface:lan1|ip_address:X.Y.Z.17|name=X.Y.Z.17
node:server1|interface:lan1|ip_address:X.Y.Z.17|netmask=255.255.248.0
node:server1|interface:lan1|ip_address:X.Y.Z.17|subnet=X.Y.Z.0
node:server1|interface:lan1|ip_address:X.Y.Z.17|route_id=1
node:server1|interface:lan1|ip_address:X.Y.Z.17|heartbeat=true
node:server1|interface:lan2|ip_address:X.Y.Z.17|name=X.Y.Z.17
node:server1|interface:lan2|ip_address:X.Y.Z.17|netmask=255.255.248.0
node:server1|interface:lan2|ip_address:X.Y.Z.17|subnet=X.Y.Z.0
node:server1|interface:lan2|ip_address:X.Y.Z.17|route_id=1
node:server1|interface:lan2|ip_address:X.Y.Z.17|heartbeat=true
我想完成如下的HOH:
%hoh = (
'node:server1' => {
name => 'server1',
status => 'up',
...,
summary => 'ok',
'interface:lan1' => {
'ip_address:X.Y.Z.17' => {
name => 'X.Y.Z.17',
netmask => '255.255.248.0',
},
...,
},
'nterface:lan2' => {
'ip_address:X.Y.Z.18' => {
name => 'X.Y.Z.18',
netmask => '255.255.248.0',
},
...,
},
},
'node:server2' => ...,
);
答案 0 :(得分:1)
这样的事情应该这样做:
use warnings;
use strict;
use Data::Dumper;
my %href;
while (my $line = <DATA>) { # or wherever you're reading from
next if $line =~ /^\s*$/;
chomp $line;
my @parts = split /\|/, $line;
my ($subkey, $value) = split /=/, pop @parts;
my $r = \%href;
for my $part (@parts) {
$r->{$part} = {} unless defined $r->{$part}; # perl < v5.10
# if you're using perl >= v5.10, you can do this instead:
# $r->{part} //= {};
$r = $r->{$part};
}
$r->{$subkey} = $value;
}
print Dumper(\%href);
答案 1 :(得分:1)
改编自Re: hashes recursively(来自PerlMonks的超级搜索):
use warnings;
use strict;
my %data;
while (<DATA>) {
next unless /\S/;
chomp;
Define(\%data, split /[|=]/)
}
use Data::Dumper;
$Data::Dumper::Sortkeys=1;
$Data::Dumper::Indent=1;
print Dumper(\%data);
sub Define { # value returned not used above,
# but can be useful for some other cases
my $href = shift;
my $key = shift or return $href;
defined ( $href -> { $key } ) or $href -> { $key } = {};
my $value = shift or return $href -> { $key };
@_ and return Define( $href -> { $key }, $value, @_ );
return $href -> { $key } = $value;
}
__DATA__
node:server1|interface:lan1|ip_address:X.Y.Z.17|name=X.Y.Z.17
node:server1|interface:lan1|ip_address:X.Y.Z.17|netmask=255.255.248.0
node:server1|interface:lan1|ip_address:X.Y.Z.17|subnet=X.Y.Z.0
node:server1|interface:lan1|ip_address:X.Y.Z.17|route_id=1
node:server1|interface:lan1|ip_address:X.Y.Z.17|heartbeat=true
node:server1|interface:lan2|ip_address:X.Y.Z.17|name=X.Y.Z.17
node:server1|interface:lan2|ip_address:X.Y.Z.17|netmask=255.255.248.0
node:server1|interface:lan2|ip_address:X.Y.Z.17|subnet=X.Y.Z.0
node:server1|interface:lan2|ip_address:X.Y.Z.17|route_id=1
node:server1|interface:lan2|ip_address:X.Y.Z.17|heartbeat=true
输出:
$VAR1 = {
'node:server1' => {
'interface:lan1' => {
'ip_address:X.Y.Z.17' => {
'heartbeat' => 'true',
'name' => 'X.Y.Z.17',
'netmask' => '255.255.248.0',
'route_id' => '1',
'subnet' => 'X.Y.Z.0'
}
},
'interface:lan2' => {
'ip_address:X.Y.Z.17' => {
'heartbeat' => 'true',
'name' => 'X.Y.Z.17',
'netmask' => '255.255.248.0',
'route_id' => '1',
'subnet' => 'X.Y.Z.0'
}
}
}
};