我有以下AWK脚本,它计算字段1中元素的出现次数,当完成读取整个文件时,打印每个元素和重复次数。
awk '{a[$1]++} END{ for(i in a){print i"-->"a[i]} }' file
我对perl非常新,我不知道它是如何相同的。到目前为止我的内容如下,但语法不正确。提前谢谢。
perl -lane '$a{$F[1]}++ END{foreach $a {print $a} }' file
____________________________________ UPDATE 的 ______________________________________
嗨,谢谢你的回答。实际输入文件有3400万行,awk和Perl之间的执行时间快3倍或更多。 awk比perl快吗?
awk '{a[$1]++}END{for(i in a){print i"-->"a[i]}}' file #--> 2:45 aprox
perl -lane '$a{$F[0]}++;END{foreach my $k (keys %a){ print "$k --> $a{$k}" } }' file #--> 7 min aprox
perl -lanE'$a{$F[0]}++; END { say "$_ => $a{$_}" for keys %a }' file # -->9 min aprox
答案 0 :(得分:1)
相当于您的awk
行
perl -lanE'$a{$F[0]}++; END { say "$_ => $a{$_}" for keys %a }' file
按-a
,该行会分为@F
中的字段,因此您希望$F[0]
作为哈希%a
中的键,其值由{{{}处理1}}。哈希在密钥上迭代并打印在++
块中。
然而,效率比较出现了。改善这种情况的一种方法是不使用END
获取线路上的所有字段,因为只需要第一个字段。在两种想到的方式之间
-a
和
perl -nE'$a{(/(\S+)/)[0]}++; END { ... }'
{8}行文件的perl -nE'$a{(split " ", $_, 2)[0]}++; END { ... }'
与split
的正则表达式明显加快了3.63s
。
对于4.41s
行,这仍然落后1.99s
。因此,awk 似乎更快完成此任务。
我的800万行文件的时间总结(几次运行的平均值)
awk (question) 1.99s perl (split) 3.63s perl (regex) 4.41s perl (like awk) 5.61s
这些时间相差几十毫秒(几个0.01秒)。
答案 1 :(得分:1)
输入文件显然会有所不同,但Perl 5.22.1在我的3350万行测试文件(12.23 vs 12.52秒)上略低于Awk 4.1.3。
schumack@daddyo2 10-02T18:25:17 54> wc -l listbig
33521910 listbig
schumack@daddyo2 10-02T18:25:58 55> /usr/bin/time -f '%E %P' awk '{a[$1]++} END{ for(i in a){print i"-->"a[i]} }' listbig
1-->9434310
2-->1605840
3-->9635040
4-->5218980
5-->4416060
7-->802920
8-->802920
9-->802920
12-->802920
0:12.52 99%
schumack@daddyo2 10-02T18:26:17 56> /usr/bin/time -f '%E %P' perl -lne '$_=~s/^(\S+) .*/$1/; $a{$_}++; END{foreach $i (keys %a){print "$i-->$a{$i}"}}' listbig
1-->9434310
5-->4416060
2-->1605840
3-->9635040
12-->802920
8-->802920
9-->802920
4-->5218980
7-->802920
0:12.23 99%
答案 2 :(得分:1)
好的,Ger,还有一次:-) 我将我的Perl升级到我可用的最新版本并制作了一个类似你所描述的文件(在第1列和唯一列中每行有3450万行16位数字):
schumack@linux2 52> wc -l listbig
34521909 listbig
schumack@linux2 53> head -3 listbig
1111111111111111
3333333333333333
4444444444444444
然后我运行了一个专门的Perl行(适用于此文件,但与awk行不同)。和以前一样,我使用/ usr / bin / time定时运行:
schumack@linux2 54> /usr/bin/time -f '%E %P' /usr/local/bin/perl -lne 'chomp; $a{$_}++; END{foreach $i (keys %a){print "$i-->$a{$i}"}}' listbig
5555555555555555-->4547796
1111111111111111-->9715747
9999999999999999-->826872
3333333333333333-->9922465
1212121212121212-->826872
4444444444444444-->5374669
2222222222222222-->1653744
8888888888888888-->826872
7777777777777777-->826872
0:12.20 99%
schumack@linux2 55> /usr/bin/time -f '%E %P' awk '{a[$1]++} END{ for(i in a){print i"-->"a[i]} }' listbig
1111111111111111-->9715747
2222222222222222-->1653744
3333333333333333-->9922465
4444444444444444-->5374669
5555555555555555-->4547796
1212121212121212-->826872
7777777777777777-->826872
8888888888888888-->826872
9999999999999999-->826872
0:12.61 99%
perl和awk在3450万行文件上运行速度非常快,并且相距不到半秒。 好奇您目前使用的是什么类型的机器/ OS / Perl版本。我在华硕笔记本电脑上测试了大约4年,拥有英特尔I7。我使用的是Ubuntu 16.04和Perl v5.26.1
无论如何,感谢您使用Perl的理由!
玩得开心, 肯
答案 3 :(得分:0)
这种破坏性的方法是我提出的最快的方法:
perl -lne '$_=~s/\s.*//; $a{$_}++; END{foreach $i (keys %a){print "$i-->$a{$i}"}}' file
然而,它仍然不如awk快。
答案 4 :(得分:-1)
您可以浏览a2p
$ cat file
1
1
2
3
3
3
$ perl -lane '$a{$F[0]}++;END{foreach my $k (keys %a){ print "$k --> $a{$k}" } }' file
1 --> 2
2 --> 1
3 --> 3
$ awk '{a[$1]++} END{ for(i in a){print i" --> "a[i]} }' file
1 --> 2
2 --> 1
3 --> 3