聚合行和总结列

时间:2017-06-28 16:00:03

标签: linux bash shell unix awk

我有一个包含以下行的文件:

01323874;291874;-;000000000000003030;2511011999;-;000000000000000000 
01323874;291874;-;000000000012920840;2511011999;+;000002910023874000 
01323872;291872;-;000000000000008750;2511011999;-;000000000000008750 
01323872;291872;+;000000000609396980;          ;+;000000000000000000 
01323778;      ;-;000000000468442930;          ;+;000000000000000000 
01323778;      ;+;000000005166500460;          ;+;000000000000000000
01323778;      ;-;000000000469421100;2511021000;+;000000000469421100 
01323778;291778;-;000000000361156930;2511021000;-;000000000361156930
01323778;      ;-;000000000186088530;2511021000;+;000000000186088530 
01323778;291778;-;000000000017602470;2511021000;-;000000000017602470

我想基于第一列汇总行:

总结第4列的值,同时考虑第3列中的符号(+/-)。

总结第7列的值,同时考虑第6列中的符号(+/-)。

01323874;291874;-;000000000012923871;2511011999;+;000002910023874000
01323872;291872;+;000000000609388230;2511011999;-;000000000000008750
01323778;291778;+;000000003663788500;2511021000;+;000000000276750230

我已成功生成格式良好的行但无法找到聚合它们的方法。您的帮助将非常感激。

2 个答案:

答案 0 :(得分:4)

kent$  cat f
01323874;291874;-;000000000000003030;2511011999;-;000000000000000000
01323874;291874;-;000000000012920840;2511011999;+;000002910023874000
01323872;291872;-;000000000000008750;2511011999;-;000000000000008750
01323872;291872;+;000000000609396980;          ;+;000000000000000000
01323778;      ;-;000000000468442930;          ;+;000000000000000000
01323778;      ;+;000000005166500460;          ;+;000000000000000000
01323778;      ;-;000000000469421100;2511021000;+;000000000469421100
01323778;291778;-;000000000361156930;2511021000;-;000000000361156930
01323778;      ;-;000000000186088530;2511021000;+;000000000186088530
01323778;291778;-;000000000017602470;2511021000;-;000000000017602470

输出

kent$  awk -F';' '{a[$1]=(1*$2?$2:a[$1]); b[$1]+=$3=="-"?-$4:$4;
                   c[$1]=(1*$5?$5:c[$1]); d[$1]+=$6=="-"?-$7:$7}
        END{for(x in a)
               printf "%s;%s;%s;%018d;%s;%s;%018d\n",
                        x,a[x],
                        (b[x]>0?"+":"-"),(b[x]<0?-b[x]:b[x]),c[x],
                        (d[x]>0?"+":"-"),(d[x]<0?-d[x]:d[x])}' f
01323872;291872;+;000000000609388230;2511011999;-;000000000000008750
01323778;291778;+;000000003663788500;2511021000;+;000000000276750230
01323874;291874;-;000000000012923870;2511011999;+;000002910023874000

答案 1 :(得分:0)

awk 解决方案:

awk -F';' 'function get_sign(n){ 
               return (n<0)? "-":"+" 
           }
           { 
               a[$1]+=int($3$4); b[$1]+=int($6$7); 
               if ($2*1) fld2[$1]=$2; if ($5*1) fld5[$1]=$5 
           }
           END{ 
               for(i in a) print i, fld2[i], get_sign(a[i]),
               sprintf("%018d",(a[i]>0)? a[i]:a[i]*-1), fld5[i], get_sign(b[i]),
               sprintf("%018d",(b[i]>0)? b[i]:b[i]*-1) 
           }' OFS=';' file

输出:

01323872;291872;+;000000000609388230;2511011999;-;000000000000008750
01323778;291778;+;000000003663788500;2511021000;+;000000000276750230
01323874;291874;-;000000000012923870;2511011999;+;000002910023874000
  • function get_sign(n) { ... } - 函数,定义数字参数n是正数还是负数并返回相应的符号