【问题标题】:Sum of 2nd and 3rd column for same value in 1st column第 1 列中相同值的第 2 列和第 3 列之和
【发布时间】:2019-09-12 08:34:22
【问题描述】:

我想将第 2 列和第 3 列中的值相加,以获得第 1 列中的相同值

1555971000 6 1   
1555971000 0 2  
1555971300 2 0  
1555971300 3 0 

输出会是这样的

1555971000 6 3  
1555971300 5 0 

我试过下面的命令

awk -F" " '{b[$2]+=$1} END { for (i in b) { print b[i],i } } '

但这似乎只适用于一列。

【问题讨论】:

    标签: linux shell awk sed scripting


    【解决方案1】:

    这是另一种读取 Input_file 2 次的方法,它将提供与 Input_file 的序列相同的输出。

    awk 'FNR==NR{a[$1]+=$2;b[$1]+=$3;next} ($1 in a){print $1,a[$1],b[$1];delete a[$1]}' Input_file Input_file
    

    【讨论】:

      【解决方案2】:

      如果 'd' 中的数据没有排序,则在 gnu awk 上尝试过,

      awk 'BEGIN{f=1} {if($1==a||f){b+=$2;c+=$3;f=0} else{print a,b,c;b=$2;c=$3} a=$1} END{print a,b,c}' d
      

      用 gnu awk 排序

      awk '{w[NR]=$0} END{asort(w);f=1;for(;i++<NR;){split(w[i],v);if(v[1]==a||f){f=0;b+=v[2];c+=v[3]} else{print a,b,c;b=v[2];c=v[3];} a=v[1]} print a,b,c;}' d
      

      【讨论】:

        【解决方案3】:

        你可以用awk做到这一点,首先保存第一条记录中的字段,然后对于所有后续记录,比较第一个字段是否匹配,如果匹配,则添加字段二和三的内容并继续。如果第一个字段不匹配,则输出您的第一个字段和运行总和,例如

        awk '{ 
            if ($1 == a) { 
                b+=$2; c+=$3; 
            }
            else {
                print a, b, c; a=$1; b=$2; c=$3;
            }
        } END { print a, b, c; }' file
        

        file中输入,您可以将上述内容复制并粘贴到您的终端并获得以下内容:

        使用/输出示例

        $ awk '{
        >     if ($1 == a) {
        >         b+=$2; c+=$3;
        >     }
        >     else {
        >         print a, b, c; a=$1; b=$2; c=$3;
        >     }
        > } END { print a, b, c; }' file
        
        1555971000 6 3
        1555971300 5 0
        

        使用 awk 数组

        使用不需要按排序顺序输入的数组的更短更简洁的替代方法是:

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

        (相同的输出)

        如果您的数据文件以随机顺序包含以下行,例如

        1555971300 2 0
        1555971000 0 2
        1555971000 6 1
        1555971300 3 0
        

        【讨论】:

        • 其实BEGIN应该去掉:)我从一个方向开始,在另一个方向结束。
        • @DavidCRankin 如果您没有按顺序排列所有列 1 $1,则您的第一个解决方案将不起作用。例如,将输入的第 1 行移动到第 4 行(在文件末尾)
        • 是的,这在第二种方法的介绍中进行了解释。第一个是在没有数组的情况下完成的,第二个是引入它们。好眼力。
        【解决方案4】:

        另一个awk 可以工作,无论记录的任何顺序,无论它们是否未排序:

        awk '{r[$1]++}
             r[$1]==1{o[++c]=$1}
             {f[$1]+=$2;s[$1]+=$3}
             END{for(i=1;i<=c;i++){print o[i],f[o[i]],s[o[i]]}}' file
        

        【讨论】:

          【解决方案5】:

          假设你写的时候:

          awk -F" " '{b[$2]+=$1} END { for (i in b) { print b[i],i } } '
          

          你打算写:

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

          弄清楚这应该不是一个巨大的飞跃:

          $ awk '{ b[$1]+=$2; c[$1]+=$3 } END{ for (i in b) print i,b[i],c[i] }' file
          1555971000 6 3
          1555971300 5 0
          

          请阅读 Arnold Robbins 的《Effective Awk Programming》第 4 版一书,然后阅读一两段关于字段和数组的内容。

          【讨论】:

            猜你喜欢
            • 2018-06-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-10-20
            • 2018-11-02
            • 2014-07-30
            相关资源
            最近更新 更多