需要根据管道分隔符对最后一列求和

需要根据管道分隔符对最后一列求和

我的输入有大量行

11|ABCD|19900101123123445455|555|AAA|50505050|0000009030
11|ABCD|19900101123123445455|555|AAA|50505050|0000000199
13|ABCD|201803010YYY66666666|600|ETC|20180300|0000084099
11|ABCD|19900101123123445455|555|AAA|50505050|0008995001

我需要得到低于输出

11|ABCD|19900101123123445455|555|AAA|50505050|9004230
13|ABCD|201803010YYY66666666|600|ETC|20180300|84099

我一直在尝试使用下面的 awk,但对数组的了解太有限。

cat test|awk -F"|" '{ a[$1]++;b[$2]++;c[$3]++;d[$4]++;e[$5]++;f[$6]+=$6 }; END { for (i in a); print i, f[i]}'

我需要对第 6 列的最后一列求和,并打印所有前 5 列,这些列由管道分隔,最后 6 列作为第 6 列的总和。

答案1

GNU datamash命令:

$ datamash -t'|' -s -g 1,2,3,4,5,6 sum 7 < infile
11|ABCD|19900101123123445455|555|AAA|50505050|9004230
13|ABCD|201803010YYY66666666|600|ETC|20180300|8409

datamash v1.2+,您也可以指定列范围。

$ datamash -t'|' -s -g 1-6 sum 7 < infile

或者最短AWK替代方案以及您在哪里列,您不应一一指定所有列:

awk -F'|' '{x=$NF;NF--; a[$0]+=x} END{for(i in a) print i, a[i]}' OFS='|' infile

答案2

Awk解决方案:

awk 'BEGIN{ FS=OFS="|" }
     { a[$1 FS $2 FS $3 FS $4 FS $5 FS $6] += $7 }
     END{ for (i in a) print i, a[i] }' file

输出:

11|ABCD|19900101123123445455|555|AAA|50505050|9004230
13|ABCD|201803010YYY66666666|600|ETC|20180300|84099

答案3

这个想法是正确的,但对于这样的要求,您创建哈希键作为除最后一列之外的值,并使用该键对最后一列中的值求和。一旦子句中的所有行都得到处理,END我们就会打印总和值

awk '
     BEGIN {FS=OFS="|"} {
         hashKey = ""
         for(i=1;i<=(NF-1); i++) {
             hashKey = ( hashKey ? (hashKey FS $i):$i )
         }
         total[hashKey]+=$NF
     }
     END { for ( j in total ) print j, total[j] }
' file

答案4

和 Perl

perl -lne '
    $sum{$1} += $2 if /(.*)\|(.*)/
 } END {
    print "$_|$sum{$_}" for keys %sum
' file

相关内容