结果:许多行HASH(0x1948958) ARRAY(0x1978250) ./directory/filename
期望的结果:[Key of first hash] [Key of second hash] ./directory/filename #(elements of array, currently working)
Catch:应该进行N级结构,因此我尝试使用Data :: Walk。
当我走结构时,我真正想要做的是引用正在使用的密钥。有点像Data :: Dumper但是以制表符分隔而不是代码格式。我认为可能的解决方案(按优先顺序排列)是:
use strict;
use File::Basename;
use Data::Walk;
my $files;
while (<>) {
chomp;
#ls -l output in a file; referencing filename from it (8th column)
my @line = split(/ /, $_, 8);
#fileparse exported by File::Basename
my ($name,$path) = fileparse($line[7]);
open (my $fh, '<', $path . $name);
my $sha = Digest::SHA->new('sha1');
$sha->addfile($fh);
#finding files by basename, then unique hash, then however many places it is stored.
#question not why I don't use the hash as the first field.
#basename digest path
push(@{$files->{$name}->{$sha->hexdigest}}, $path . $name);
}
my @val;
sub walkit {
$val[$Data::Walk::depth - 1] = $_;
if ($Data::Walk::depth == 3) {
print join("\t", @val), "\n";
}
}
&walk (\&walkit, %$files);
大师?
答案 0 :(得分:3)
for my $name (keys(%$files)) {
for my $digest (keys(%{$files->{$name}})) {
my @qfns = @{ $files->{$name}{$digest} };
if (@qfns > 1) {
say "For $name and $digest,";
say " $_" for @qfns;
}
}
}
(我假设您正在寻找重复项,因此当只有一个路径与名称摘要组合相关时,我什么都不打印。如果您想要打印所有内容,可以删除if
。)< / p>
其他一些清理:
use strict;
use warnings;
use 5.010;
use Digest::SHA qw( );
use File::Basename qw( basename );
sub calc_digest {
my ($qfn) = @_;
open(my $fh, '<', $qfn) or die $!;
my $sha = Digest::SHA->new('sha1');
$sha->addfile($fh);
return $sha->hexdigest();
}
my $files;
while (<>) {
my $qfn = (split)[7];
my $name = basename($path);
my $digest = calc_digest($qfn);
push @{ $files->{$name}{$digest} }, $qfn;
}
(“qfn”代表“限定文件名”,表示文件的路径,而不是$path
包含的内容。即使$line[7]
包含它,您也反复构建路径。)
答案 1 :(得分:3)
修改:反对我更好的判断,我会再次尝试回答这个问题。
这是一种打印您想要的简单方法。使用Data :: Walk是不可行的,因为当你在哈希中时你没有键上下文(你只是得到一个指向容器的指针。)
此功能适用于有些复杂的结构。当然,如果你把一个函数引用或者那些东西放在那里,它就不会给出正确的输出。
use strict;
use warnings;
my $res;
sub walk {
my ($item, $path) = @_;
if (ref $item eq 'ARRAY') {
foreach (@$item) {
walk($_, $path);
}
} elsif (ref $item eq 'HASH') {
foreach (keys %$item) {
push @$path, $_;
walk($item->{$_}, $path);
pop @$path;
}
} else {
print join('-', @$path, $item), "\n";
}
}
my $struct = {
a => {
a1 => { a11 => [ 1, 2, 3 ] },
a2 => { a22 => [5, 6, 7] }
},
b => { b1 => [ 99 ], },
c => [ 100, 101, ],
d => [ 101, { d2 => { d3 => [200, 210] }, }, ],
};
walk $struct;