我希望遍历这些通过给定路径的数据结构(基本上是目录结构)。
目标是列出根/基本路径,然后列出所有子path
(如果存在)以及存在的每个子path
,列出file
子路径。
我知道这可能需要通过HoH或AoH循环。有人能告诉我perl技术吗?感谢。
基础级别:/ work / eng / feeds
$VAR1 = {
'recursive' => 'no',
'version' => '0.20.202.1.1101050227',
'time' => '2011-10-26T00:20:18+0000',
'filter' => '.*',
'path' => '/work/eng/feeds',
'directory' => [
{
'owner' => 'tst_act',
'group' => 'eng',
'permission' => 'drwxrwxr-x',
'path' => '/work/eng/feeds',
'accesstime' => '1970-01-01T00:00:00+0000',
'modified' => '2011-08-27T03:13:53+0000'
},
{
'owner' => 'tst_act',
'group' => 'eng',
'permission' => 'drwxr-xr-x',
'path' => '/work/eng/feeds/customer_care',
'accesstime' => '1970-01-01T00:00:00+0000',
'modified' => '2011-10-25T23:54:17+0000'
}
],
'exclude' => ''
};
下一级:/ work / eng / feeds / customer_care
$VAR1 = {
'recursive' => 'no',
'version' => '0.20.202.1.1101050227',
'time' => '2011-10-26T00:21:06+0000',
'filter' => '.*',
'path' => '/work/eng/feeds/customer_care',
'directory' => [
{
'owner' => 'tst_act',
'group' => 'eng',
'permission' => 'drwxr-xr-x',
'path' => '/work/eng/feeds/customer_care',
'accesstime' => '1970-01-01T00:00:00+0000',
'modified' => '2011-10-25T23:54:17+0000'
},
{
'owner' => 'tst_act',
'group' => 'eng',
'permission' => 'drwx------',
'path' => '/work/eng/feeds/customer_care/abc',
'accesstime' => '1970-01-01T00:00:00+0000',
'modified' => '2011-10-25T17:12:56+0000'
},
{
'owner' => 'tst_act',
'group' => 'eng',
'permission' => 'drwx------',
'path' => '/work/eng/feeds/customer_care/def',
'accesstime' => '1970-01-01T00:00:00+0000',
'modified' => '2011-10-25T21:05:50+0000'
},
{
'owner' => 'tst_act',
'group' => 'eng',
'permission' => 'drwx------',
'path' => '/work/eng/feeds/customer_care/test',
'accesstime' => '1970-01-01T00:00:00+0000',
'modified' => '2011-10-25T21:28:14+0000'
}
],
'exclude' => ''
};
还有一个级别:/ work / eng / feeds / customer_care / test(此处存在文件)
$VAR1 = {
'recursive' => 'no',
'version' => '0.20.202.1.1101050227',
'time' => '2011-10-26T00:30:02+0000',
'filter' => '.*',
'file' => {
'owner' => 'tst_act',
'replication' => '3',
'blocksize' => '134217728',
'permission' => '-rw-------',
'path' => '/work/eng/feeds/customer_care/test/q_data_20111023.dat',
'modified' => '2011-10-26T00:29:46+0000',
'size' => '379085',
'group' => 'eng',
'accesstime' => '2011-10-26T00:29:46+0000'
},
'path' => '/work/eng/feeds/customer_care/test',
'directory' => {
'owner' => 'tst_act',
'group' => 'eng',
'permission' => 'drwx------',
'path' => '/work/eng/feeds/customer_care/test',
'accesstime' => '1970-01-01T00:00:00+0000',
'modified' => '2011-10-26T00:29:46+0000'
},
'exclude' => ''
};
答案 0 :(得分:3)
这是一个启动者:
sub list_path_files {
my ($data) = @_;
say $data->{path}; # get value from a hashref
my @directories;
# check whether it is a single value or an arrayref of values
if (ref $data->{directory} eq 'ARRAY') {
@directories = @{ $data->{directory} }; # dereference the arrayref to get an AoH
} else {
@directories = $data->{directory}; # just get the single value
}
for my $dir (@directories) {
next if $dir->{path} eq $data->{path};
say $dir->{path};
}
# I'll leave the rest for you to do
}
<强>更新强>
要迭代hashref,首先需要取消引用,然后使用each
,keys
或values
函数:
%hash = %$VAR1; # dereference
while (my ($key, $value) = each %hash) {...}
for my $key (keys %$VAR1) {
my $value = $VAR1->{$key};
}
for my $value (values %$VAR1) {...}
如果哈希值是嵌套结构,您还需要取消引用哈希值:
if (ref $val eq '') {
# $val is just a scalar - don't need to deref
}
elsif (ref $val eq 'HASH') {
my %hash = %$val;
}
elsif (ref $val eq 'ARRAY') {
my @array = @$val;
}
答案 1 :(得分:0)
由于数据中存在XML-esque时间戳,并且目录/文件结构是散列或哈希数组,我猜你要解析XML来构建初始哈希?
如果您正在使用XML :: Simple从XML中读取它,
ForceArray =&gt; ['目录','档案']
将避免检查ref类型。
然后你可以简化为这样的事情:
my %fs
for my $item (values %your_giant_hash_with_fs_data) {
$fs{$_->{path}}='d' for ( @{ $item->{directory} } );
$fs{$_->{path}}='f' for ( @{ $item->{file} } );
}
my $search_path='/work/eng/feeds/customer_care/test';
my $search=qr/^$search_path/;
for (sort keys %fs) {
print "$fs{$_} $_\n" if /$search/;
}
输出:
d /work/eng/feeds/customer_care/test
f /work/eng/feeds/customer_care/test/q_data_20111023.dat
或者如果您不想创建临时结构
my $search_path='/work/eng/feeds/customer_care/test';
my $search=qr/^$search_path/;
{
my %seen;
for my $item (values %your_giant_hash_with_fs_data) {
for my $type (qw/directory file/) {
for ( @{ $item->{$type} } ) {
if ( $_->{path}=~/$search/ and not $seen{$_->{path}} ) {
printf("%-10s%s\n",$type,$_->{path});
$seen{$_->{path}}=1;
}
}
}
}
}
这只适用于你的每条路径都是绝对的,绝对路径不能重复