0

我真的很坚持这一点,希望能得到任何帮助!

我有一个 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 专家对此的帮助。

4

2 回答 2

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容量时才使用。我只是为了完整性才包括它。

于 2013-05-23T02:44:54.103 回答
1

纯重击:

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
于 2013-05-23T09:29:19.107 回答