简单的读取列和总和第3列

时间:2013-05-23 02:39:58

标签: bash awk

我真的非常坚持这一点,并感谢任何帮助!

我有一个3列的CSV文件。如果一行具有相同的第一列和第二列作为另一行,则将这些行中的第三列添加在一起。

Input:
7514    128    1
7514    128    2
7514    128    1
7514    544    1
7514    544    3
5807    338    4
5807    338    1

Output:
7514    128    4
7514    544    4
5807    338    5

我试过

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

但它只给了我

7514 1472
5807 676

这不是我想要的。非常感谢任何awk专家对此的帮助。

2 个答案:

答案 0 :(得分:4)

我相信你想要这样的东西:

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

(你真的不需要next),如以下成绩单所示:

$ echo '7514    128    1
7514    128    2
7514    128    1
7514    544    1
7514    544    3
5807    338    4
5807    338    1' | awk '{A[$1" "$2]+=$3}END{for(i in A){print i,A[i]}}'

7514 128 4
5807 338 5
7514 544 4

您的原始代码根据第1列中的键对第2列求和。

您需要执行的操作(以及上述awk脚本所做的)是根据 1和2 列创建的键对 3 列进行求和。


而且,如果数据总是被排序并且可能有批次的密钥(超出awk可以处理的范围),您只需使用:

awk 'NR==1           {last=$1" "$2; sum=$3; next}
     last!=$1" "$2   {print last" "sum; last=$1" "$2; sum=0}
                     {sum += $3}
     END             {print last" "sum}'

这是你的经典"排序列表处理。

它没有数组存储解决方案那么优雅,所以如果数组超出awk的容量,那么应该只使用。我只是为了完整性而加入它。

答案 1 :(得分:1)

Pure Bash:

declare -A sum                      # an associative array

while read k1 k2 val ; do
  ((sum[$k1-$k2]+=val))             # combine keys to one
done < "$infile"

for k in ${!sum[*]}; do
  echo -e "${k/-/ } ${sum[$k]}"     # separate keys
done

输出:

7514 544 4
7514 128 4
5807 338 5