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

ben*_*oth 5 unix bash uniq

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

例如给出:

a.cnt:

   1 a
   2 c
Run Code Online (Sandbox Code Playgroud)

b.cnt:

   2 b
   1 c
Run Code Online (Sandbox Code Playgroud)

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

   1 a
   2 b
   3 c
Run Code Online (Sandbox Code Playgroud)

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

编辑:

谢谢你到目前为止的答案!

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

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

fed*_*qui 9

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

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

所以,如果你让我们说10个文件,你只需要做cat f1 f2 ...,然后管道awk.

如果文件名碰巧共享一个模式,你也可以这样做(感谢AdrianFrühwirth!):

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

因此,例如,这将考虑其扩展名为的所有文件cnt.


更新

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

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

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

awk '{count=$1; $1=""; a[$0]+=count} END{for (i in a) print a[i],i}' *cnt
Run Code Online (Sandbox Code Playgroud)

请注意,实际上您不需要sort | uniq -c重定向到cnt文件然后执行此重新计数.您可以使用以下内容完成所有操作:

awk '{a[$0]++} END{for (i in a) print a[i], i}' file
Run Code Online (Sandbox Code Playgroud)

$ 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}'
4  text here
9  blabla
4  and some
4  and other things
Run Code Online (Sandbox Code Playgroud)

关于第二评论:

$ 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
Run Code Online (Sandbox Code Playgroud)


anu*_*ava 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
Run Code Online (Sandbox Code Playgroud)


Adr*_*rth 5

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