【问题标题】:how to aggregate counts in a bash one-liner如何在 bash 单行中汇总计数
【发布时间】:2014-03-13 15:52:55
【问题描述】:

我经常使用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 是任意字符串,包含任意空格怎么办?
  • 如果文件太大而无法放入内存怎么办?对于这种情况,是否有一些 sort | uniq -c 样式的命令行选项一次只查看两行?

【问题讨论】:

    标签: bash unix uniq


    【解决方案1】:

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

    $ 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 是任意字符串,包含任意空格怎么办?
    • 如果文件太大而无法放入内存怎么办?对于这种情况,是否有一些 sort | uniq -c 样式的命令行选项一次只查看两行?

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

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

    请注意,实际上您不需要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}'
    4  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
    

    【讨论】:

    • 或者,你知道,跳过管道:-)
    • @dhokas 绝对。用更改更新了帖子,感谢您的报告!
    【解决方案2】:

    使用 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
    

    【讨论】:

      【解决方案3】:
      $ awk '{a[$2]+=$1}END{for(i in a){print a[i], i}}' a.cnt b.cnt
      1 a
      2 b
      3 c
      

      【讨论】:

        猜你喜欢
        • 2018-06-06
        • 1970-01-01
        • 1970-01-01
        • 2019-08-18
        • 1970-01-01
        • 2013-06-07
        • 1970-01-01
        • 1970-01-01
        • 2021-08-23
        相关资源
        最近更新 更多