加载字段 1 并在 END{} 处打印,相当于 Perl 中的 awk
Load field 1 and print at the END{} equivalent awk in Perl
我有以下 AWK 脚本,它计算字段 1 中元素的出现次数,并在完成读取整个文件时打印每个元素和重复次数。
awk '{a[]++} 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[]++}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
相当于你的awk
行
perl -lanE'$a{$F[0]}++; END { say "$_ => $a{$_}" for keys %a }' file
通过-a
,该行被分解为@F
中的字段,因此您希望$F[0]
作为散列%a
中的键,其值由处理的计数器++
。散列在键上迭代并打印在 END
块中。
不过,效率比较就上来了。改进这一点的一种方法是不获取行中的所有字段,使用 -a
完成,因为只需要第一个。在想到的两种方式之间
perl -nE'$a{(/(\S+)/)[0]}++; END { ... }'
和
perl -nE'$a{(split " ", $_, 2)[0]}++; END { ... }'
split
在 8M 行的文件中,其 3.63s
与正则表达式的 4.41s
相比,速度明显更快。
对于您的 awk
行,这仍然落后于 1.99s
。所以看起来 awk 对于这个任务更快。
我对 800 万行文件的计时总结(几次运行的平均值)
awk (question) 1.99s
perl (split) 3.63s
perl (regex) 4.41s
perl (like awk) 5.61s
这些时间在运行过程中会相差几十毫秒(几 0.01 秒)。
你可以通过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[]++} END{ for(i in a){print i" --> "a[i]} }' file
1 --> 2
2 --> 1
3 --> 3
这个破坏性的方法是我想出最快的:
perl -lne '$_=~s/\s.*//; $a{$_}++; END{foreach $i (keys %a){print "$i-->$a{$i}"}}' file
然而,它仍然不如 awk 快。
输入文件显然会有所不同,但在我的 3350 万行测试文件中,Perl 5.22.1 比下面的 Awk 4.1.3 稍快(12.23 对 12.52 秒)。
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[]++} 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+) .*//; $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%
好的,Ger,再来一次 :-)
我将我的 Perl 升级到我可以使用的最新版本并制作了一个如您所描述的文件(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[]++} 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 年历史的华硕笔记本电脑上进行了测试,它配备了 Intel I7。我正在使用 Ubuntu 16.04 和 Perl v5.26.1
无论如何,谢谢你让我玩 Perl!
玩得开心,
肯
我有以下 AWK 脚本,它计算字段 1 中元素的出现次数,并在完成读取整个文件时打印每个元素和重复次数。
awk '{a[]++} 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[]++}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
相当于你的awk
行
perl -lanE'$a{$F[0]}++; END { say "$_ => $a{$_}" for keys %a }' file
通过-a
,该行被分解为@F
中的字段,因此您希望$F[0]
作为散列%a
中的键,其值由处理的计数器++
。散列在键上迭代并打印在 END
块中。
不过,效率比较就上来了。改进这一点的一种方法是不获取行中的所有字段,使用 -a
完成,因为只需要第一个。在想到的两种方式之间
perl -nE'$a{(/(\S+)/)[0]}++; END { ... }'
和
perl -nE'$a{(split " ", $_, 2)[0]}++; END { ... }'
split
在 8M 行的文件中,其 3.63s
与正则表达式的 4.41s
相比,速度明显更快。
对于您的 awk
行,这仍然落后于 1.99s
。所以看起来 awk 对于这个任务更快。
我对 800 万行文件的计时总结(几次运行的平均值)
awk (question) 1.99s perl (split) 3.63s perl (regex) 4.41s perl (like awk) 5.61s
这些时间在运行过程中会相差几十毫秒(几 0.01 秒)。
你可以通过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[]++} END{ for(i in a){print i" --> "a[i]} }' file
1 --> 2
2 --> 1
3 --> 3
这个破坏性的方法是我想出最快的:
perl -lne '$_=~s/\s.*//; $a{$_}++; END{foreach $i (keys %a){print "$i-->$a{$i}"}}' file
然而,它仍然不如 awk 快。
输入文件显然会有所不同,但在我的 3350 万行测试文件中,Perl 5.22.1 比下面的 Awk 4.1.3 稍快(12.23 对 12.52 秒)。
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[]++} 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+) .*//; $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%
好的,Ger,再来一次 :-) 我将我的 Perl 升级到我可以使用的最新版本并制作了一个如您所描述的文件(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[]++} 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 年历史的华硕笔记本电脑上进行了测试,它配备了 Intel I7。我正在使用 Ubuntu 16.04 和 Perl v5.26.1
无论如何,谢谢你让我玩 Perl!
玩得开心, 肯