我经常以gnu parallel的方式使用包含各种对象计数的大文件结束:
1201 object1
804 object1
327 object2
3828 object1
29 object2
277 object3
...
这通常有数千行,各种对象没有特定的顺序。我想要一个每个对象总数的总和。我通常的方法是将Perl单行放在一起,如下所示:
perl -lane '$O{$F[1]} += $F[0]; END {foreach $k (keys %O) {print "$k: $O{$k}"}}' countsfile
我通常会有一个由并行,awk,grep,sort,uniq,cut等组成的管道,每个管道都有相当简洁的参数。 perl hack是一个例外:它的输入时间很长,而且比管道的其他部分复杂得多。我总是觉得我在键入时指的远远超过我真正需要的。
所以我的问题是:是否有一种技术或实用工具可以让我在没有每次编写完整脚本的情况下执行此操作?我希望能够在不使用perl,awk,R或其他实现通用语言的系统的情况下完成此操作。
答案 0 :(得分:2)
您的大多数代码都在END
块中以显示哈希值。您可以使用while
代替for
perl -lanE '$O{$F[1]} += $F[0]; END {say "@v" while @v = each %O}}' countsfile
object1 5833
object3 277
object2 356
或者,如果您倾向于安装Data::Dump
,则可能完全失去循环
perl -MData::Dump -lanE '$O{$F[1]} += $F[0]; END {dd \%O}' countsfile
{ object1 => 5833, object2 => 356, object3 => 277 }
您甚至可以使用语法来避免需要END
块
perl -lanE '$O{$F[1]} += $F[0];}{say "@v" while @v = each %O' countsfile
答案 1 :(得分:0)
使用awk
:
awk '{sum[$2]+=$1}END{for(i in sum)print i,sum[i]}' File
使用第二个单词(objectx
)作为索引,更新sum
数组。这会将第一个字段(number
)加到sum[objectx]
。最后,打印每个索引和该索引处的元素(这将是总和)。
<强>示例:强>
AMD$ awk '{sum[$2]+=$1}END{for(i in sum)print i,sum[i]}' File
object1 5833
object2 356
object3 277