如何聚合bash one-liner中的计数

时间:2014-03-13 15:52:55

标签: bash unix uniq

我经常使用sort | uniq -c来计算统计数据。 现在,如果我有两个带有这种计数统计数据的文件,我想将它们放在一起并添加计数。 (我知道我可以附加原始文件并在那里计算,但我们假设只有计数文件可以访问)。

例如:

a.cnt:

   1 a
   2 c

b.cnt:

   2 b
   1 c

我想连接并得到以下输出:

   1 a
   2 b
   3 c

在shell中执行此操作的最短方法是什么?

修改

感谢目前为止的答案!

可能需要另外考虑的一些可能的方面:

  • 如果a,b,c是包含任意空格的arbritrary字符串怎么办?
  • 如果文件太大而无法放入内存怎么办?这种情况下是否有一些sort | uniq -c - 样式命令行选项,一次只能查看两行?

3 个答案:

答案 0 :(得分:8)

这适用于任何给定数量的文件:

$ cat a.cnt b.cnt | awk '{a[$2]+=$1} END{for (i in a) print a[i],i}'
1 a
2 b
3 c

因此,如果您让我们说出10个文件,您只需执行cat f1 f2 ...然后管道awk

如果文件名碰巧共享一个模式,你也可以(thanks Adrian Frühwirth!):

awk '{a[$2]+=$1} END{for (i in a) print a[i],i}' *cnt

例如,这将考虑所有扩展名为cnt的文件。


更新

  

可能需要另外考虑的一些可能的方面:

     
      
  • 如果a,b,c是包含任意空格的arbritrary字符串怎么办?
  •   
  • 如果文件太大而无法放入内存怎么办?这种情况下是否有一些sort | uniq -c - 样式命令行选项,一次只能查看两行?
  •   

在这种情况下,您可以使用其余列作为计数器的索引:

cat *cnt | awk '{count=$1; $1=""; a[$0]=count} END{for (i in a) print a[i],i}'

请注意,实际上您不需要sort | uniq -c并重定向到cnt文件,然后执行此重新计数。你可以这样做:

awk '{a[$0]++} END{for (i in a) print a[i], i}' file

实施例

$ cat a.cnt
   1 and some
   2 text here

$ cat b.cnt
   4 and some
   4 and other things
   2 text here
   9 blabla

$ cat *cnt | awk '{count=$1; $1=""; a[$0]=count} END{for (i in a) print a[i],i}'
2  text here
9  blabla
4  and some
4  and other things

关于第二条评论:

$ cat b
and some
text here
and some
and other things
text here
blabla

$ awk '{a[$0]++} END{for (i in a) print a[i], i}' b
2 and some
2 text here
1 and other things
1 blabla

答案 1 :(得分:5)

使用awk:

awk 'FNR==NR{a[$2]=$1;next} $2 in a{a[$2]+=$1}1' a.cnt b.cnt
1 a
2 b
3 c

答案 2 :(得分:5)

$ awk '{a[$2]+=$1}END{for(i in a){print a[i], i}}' a.cnt b.cnt
1 a
2 b
3 c