我一直在尝试编写一个脚本来预处理一些长文件列表,但我对Perl还没有信心(也没有能力)并且没有得到我想要的结果。
下面的脚本正在进行中,但我仍然坚持检查是否有重复,如果有人能让我知道我哪里出错了,我将不胜感激。处理重复的块似乎与我找到的示例形式相同,但它似乎不起作用。
#!/usr/bin/perl
use strict;
use warnings;
open my $fh, '<', $ARGV[0] or die "can't open: $!";
foreach my $line (<$fh>) {
# Trim list to remove directories which do not need to be checked
next if $line =~ m/Inventory/;
# MORE TO DO
next if $line =~ m/Scanned photos/;
$line =~ s/\n//; # just for a tidy list when testing
my @split = split(/\/([^\/]+)$/, $line); # separate filename from rest of path
foreach (@split) {
push (my @filenames, "$_");
# print "@filenames\n"; # check content of array
my %dupes;
foreach my $item (@filenames) {
next unless $dupes{$item}++;
print "$item\n";
}
}
}
我很难理解我的重复检查有什么问题。我知道数组包含重复项(取消注释第一个打印函数给我一个包含大量重复项的列表)。现有代码不会产生任何效果。
不是我帖子的主要目的,但我的最终目的是从列表中删除唯一的文件名,并保留在其他目录中重复的文件名。 我知道这些文件都不相同,但很多是同一文件的不同版本,这就是我专注于文件名的原因。
例如,我想要输入:
〜/图片/ 2010 / 12345678.jpg 〜/图片/ 2010 / 12341234.jpg 〜/桌面/温度/ 12345678.jpg
输出:
〜/图片/ 2010 / 12345678.jpg 〜/桌面/温度/ 12345678.jpg
所以我认为理想情况下,如果可能的话,最好根据正则表达式检查匹配的唯一性而不分裂。
答案 0 :(得分:5)
以下循环不执行任何操作,因为散列和数组仅包含每个循环迭代的一个值:
foreach (@split) {
push (my @filenames, "$_"); # add one element to lexical array
my %dupes;
foreach my $item (@filenames) { # loop one time
next unless $dupes{$item}++; # add one key to lexical hash
print "$item\n";
}
} # @filenames and %dupes goes out of scope
词法变量(用my
声明)的范围扩展到周围的块{ ... }
,在这种情况下是foreach
循环。当它们超出范围时,它们将被重置并且所有数据都将丢失。
我不知道为什么要将文件名从@split
复制到@filenames
,这似乎非常多余。重复数据删除的方法是:
my %seen;
my @uniq;
@uniq = grep !$seen{$_}++, @split;
其他信息:
您可能还有兴趣使用File::Basename
获取文件名:
use File::Basename;
my $fullpath = "~/Pictures/2010/12345678.jpg";
my $name = basename($fullpath); # 12345678.jpg
您的替换
$line =~ s/\n//;
应该是
chomp($line);
当您从文件句柄中读取时,使用for
(foreach
)表示您已读取所有行并将其存储在内存中。大多数情况下,最好使用while
,如下所示:
while (my $line = <$fh>)
答案 1 :(得分:3)
TLP的回答提供了很多好的建议。另外:
为什么同时使用数组和哈希来存储文件名?只需使用哈希作为您的一个存储解决方案,您将自动删除重复项。即:
my %filenames; #outside of the loops
...
foreach (@split) {
$filenames{$_}++;
}
现在,当您想要获取唯一文件名列表时,只需使用keys %filenames
,或者如果您希望按字母顺序使用sort keys %filenames
。并且每个哈希键的值是一个出现次数,因此如果您愿意,可以找出哪些是重复的。