File::Find::Rule 输出重复问题排查求助
排查Perl子例程输出重复问题
问题描述
子例程可正确解析哈希并返回基本正确结果,但存在输出重复问题,实际输出内容重复了一遍。
示例数据
$local_h{$local}{name} = "somefile.txt"; $local_h{$local}{size} = 12345;
子例程代码
sub already_here { foreach my $local (keys(%local_h)) { my $tmp = $local_h{$local}{name}; my $FFR_rule = File::Find::Rule ->size($local_h{$local}{size}) ->start( @volumes ); while ( defined ( my $match = $FFR_rule->match ) ) { my ( $name, $path, $suffix ) = fileparse($match); if ( $name =~ /$local_h{$local}{name}/ ) { say "\t\$name $name has been matched by size and name to:\n\t $path$name\n"; # Matches can occur multiple times, to be dealt with later/elsewhere } else { say "$match Matched by size only\n"; # Maybe this really is the location but got renamed locally. # For now I will consider it an edge-case. } } } }
实际输出
somefile.txt has been matched by size and name to: a/path/to/somefile.txt somefile.txt has been matched by size and name to: some/other/path/to/somefile.txt 34thx.foo Matched by size only somefile.txt has been matched by size and name to: a/path/to/somefile.txt somefile.txt has been matched by size and name to: some/other/path/to/somefile.txt 34thx.foo Matched by size only
预期输出
仅看到3行有效输出(含空行共4行),无重复内容。
问题根源
输出重复的核心原因是**%local_h哈希中存在多个键**,导致foreach my $local (keys(%local_h))循环执行了多次。每次循环都会重新初始化File::Find::Rule并完整遍历@volumes目录,所以同一组匹配结果会被打印多遍。
你可以在循环前添加一行代码验证键的数量:
say "Number of keys in %local_h: " . scalar keys %local_h;
如果输出大于1,就说明哈希里有多个条目,这就是重复的原因。
解决办法
根据你的实际需求选择以下方案:
方案1:确保仅处理单个文件条目
如果%local_h只需要存储一组文件信息,直接获取哈希的唯一键即可,去掉foreach循环:
sub already_here { # 取出%local_h的唯一键 my ($local) = keys(%local_h); my $target_name = $local_h{$local}{name}; my $target_size = $local_h{$local}{size}; my $FFR_rule = File::Find::Rule ->size($target_size) ->start( @volumes ); while ( defined ( my $match = $FFR_rule->match ) ) { my ( $name, $path, $suffix ) = fileparse($match); # 用\Q\E包裹文件名,避免正则元字符导致匹配异常 if ( $name =~ /\Q$target_name\E/ ) { say "\t\$name $name has been matched by size and name to:\n\t $path$name\n"; } else { say "$match Matched by size only\n"; } } }
方案2:处理多组条目但避免重复输出
如果%local_h确实需要存储多组文件信息,需要记录已经输出过的文件路径,避免重复打印:
sub already_here { # 哈希记录已输出的文件路径,避免重复 my %seen; foreach my $local (keys(%local_h)) { my $target_name = $local_h{$local}{name}; my $target_size = $local_h{$local}{size}; my $FFR_rule = File::Find::Rule ->size($target_size) ->start( @volumes ); while ( defined ( my $match = $FFR_rule->match ) ) { # 如果该文件已经输出过,直接跳过 next if $seen{$match}++; my ( $name, $path, $suffix ) = fileparse($match); if ( $name =~ /\Q$target_name\E/ ) { say "\t\$name $name has been matched by size and name to:\n\t $path$name\n"; } else { say "$match Matched by size only\n"; } } } }
内容的提问来源于stack exchange,提问作者Harry_
相关产品推荐
相关产品推荐

