Perl:重复计数

Perl:重复计数,perl,file,count,duplicates,Perl,File,Count,Duplicates,我有以下file.txt文件: AAAA BBBB AAAA CCCC EEEE AAAA 我写了一个脚本来计算副本的数量,从最高副本到最低副本排序,然后打印它们。比如: AAAA : 3 BBBB : 1 CCCC : 1 EEEE : 1 剧本是: use v5.14; use strict; my %map; chomp(my @chks = <FILE>); foreach my $load (@chks) { $map{$load} += 1; } for

我有以下file.txt文件:

AAAA
BBBB
AAAA
CCCC
EEEE
AAAA
我写了一个脚本来计算副本的数量,从最高副本到最低副本排序,然后打印它们。比如:

AAAA : 3
BBBB : 1
CCCC : 1
EEEE : 1
剧本是:

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} "
} 

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

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

解决方案是使用
:crlf
PerlIO层打开文件,或者使用
chomp

该程序必须有更多内容,因为您没有在任何地方打开
文件。此外,还可以按哈希键的词法顺序对输出进行排序,而不是按值的数字顺序

下面是我将如何编写您的代码。
:crlf
层会在输入时将CR-LF行尾转换为just-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";
}

正如我所说,您可以使用替换
chomp@chks
为@chks
使用
s/\R\z//,而不是使用
:crlf
层。
\R
将匹配来自任何系统的任何行终止符:在本例中,CR LF字符对

@mkHun:这是令人鼓舞的。非常感谢。
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";
}
AAAA : 3
CCCC : 1
BBBB : 1
EEEE : 1