Reputation: 65
This is my problem:
I have a file-system like data-structure:
%fs = (
"home" => {
"test.file" => {
type => "file",
owner => 1000,
content => "Hello World!",
},
},
"etc" => {
"passwd" => {
type => "file",
owner => 0,
content => "testuser:testusershash",
},
"conf" => {
"test.file" => {
type => "file",
owner => 1000,
content => "Hello World!",
},
},
},
);
Now, to get the content of /etc/conf/test.file
I need $fs{"etc"}{"conf"}{"test.file"}{"content"}
, but my input is an array and looks like this: ("etc","conf","test.file")
.
So, because the length of the input is varied, I don't know how to access the values of the hash. Any ideas?
Upvotes: 2
Views: 122
Reputation: 21
Path::Class accepts an array. It also gives you an object with helper methods and handles cross platform slash issues.
https://metacpan.org/module/Path::Class
Upvotes: 0
Reputation: 1128
$pname = '/etc/conf/test.file';
@names = split '/', $pname;
$fh = \%fs;
for (@names) {
$fh = $fh->{"$_"} if $_;
}
print $fh->{'content'};
Upvotes: 0
Reputation: 3037
Same logic as what others given, but uses foreach
@keys = qw(etc conf test.file content);
$r = \%fs ;
$r = $r->{$_} foreach (@keys);
print $r;
Upvotes: 1
Reputation: 126722
You can just build the hash element expression and call eval
. This is tidier if it is wrapped in a subroutine
my @path = qw/ etc conf test.file /;
print hash_at(\%fs, \@path)->{content}, "\n";
sub hash_at {
my ($hash, $path) = @_;
$path = sprintf q($hash->{'%s'}), join q('}{'), @$path;
return eval $path;
}
Upvotes: -1
Reputation: 97918
my @a = ("etc","conf","test.file");
my $h = \%fs;
while (my $v = shift @a) {
$h = $h->{$v};
}
print $h->{type};
Upvotes: 1
Reputation: 241738
You can use a loop. In each step, you proceed one level deeper into the structure.
my @path = qw/etc conf test.file/;
my %result = %fs;
while (@path) {
%result = %{ $result{shift @path} };
}
print $result{content};
You can also use Data::Diver.
Upvotes: 5