Perl:计算重复项

onl*_*lyf 1 perl file count duplicates

我有以下file.txt:

AAAA
BBBB
AAAA
CCCC
EEEE
AAAA
Run Code Online (Sandbox Code Playgroud)

我编写了一个脚本来计算重复次数,将它们从最高重复项排序到最低重复项并打印出来.喜欢 :

AAAA : 3
BBBB : 1
CCCC : 1
EEEE : 1
Run Code Online (Sandbox Code Playgroud)

该脚本是:

use v5.14;
use strict;

my %map;
chomp(my @chks = <FILE>);

foreach my $load (@chks) {
    $map{$load} += 1;
}

foreach my $key (sort keys %map) {
    say "$key : $map{$key} "
} 
Run Code Online (Sandbox Code Playgroud)

但输出结果如下:

 : 3
 : 1
 : 1
 : 1
Run Code Online (Sandbox Code Playgroud)

为什么它看不到$ key的值?

Bor*_*din 5

答案是您的输入文件来自Windows平台,它使用CR LF作为行终止符.当在同一平台上使用Perl读取文件时,通常会在输入时删除CR,但如果使用Linux系统读取文件,则它将保留在原位.Perl chomp将仅删除LF,将CR保留在每个哈希键值的末尾.这将导致在打印密钥时覆盖输出

解决方案是使用:crlfPerlIO层打开文件,或者使用除了输入之外的其他内容从输入的末尾删除CR和LF.chomp

由于您不在FILE任何地方打开,因此该程序必须有更多内容.此外,您按散列键的词法顺序排序输出,而不是值的数字顺序

以下是我编写代码的方法.该:crlf层导致CR LF行结尾在输入时仅转换为LF,chomp现在将正常运行,只留下每行中的文本

use strict;
use warnings 'all';

my $filename = 'myfile.txt';

my @chks = do {
    open my $fh, '<:crlf', $filename or die qq{Unable to open "$filename" for input: $!};
    <$fh>;
};

chomp @chks;

my %map;

++$map{$_} for @chks;

for my $key ( sort { $map{$b} <=> $map{$a} } keys %map ) {
    print "$key : $map{$key}\n";
}
Run Code Online (Sandbox Code Playgroud)

产量

AAAA : 3
CCCC : 1
BBBB : 1
EEEE : 1
Run Code Online (Sandbox Code Playgroud)

正如我所说的,而不是使用:crlf层,你可以使用替换chomp @chkss/\R\z// for @chks.在\R将匹配从任何系统中的任何行终止:在这种情况下,CR LF字符对