awk或sed对行中的类似值求和

时间:2014-05-08 03:42:10

标签: bash awk sed

我的文件的值如下:

(X1 55) (X2 99) (X3 29) (X1 3) (X3 10)
(X1 21) (X3 11) (X1 9)

是否可以通过每行Xn名称添加值:

(X1 58) (X2 99) (X3 39)
(X1 30) (X3 11)

我不确定最好使用哪种,awk,sed或......?我试过这个:

awk '{for (i=t=0;i<NF;) t+=$++i; $0=t}1' file

196
41

它显然将所有值加在一起,所以可能它有点复杂。

3 个答案:

答案 0 :(得分:6)

$ awk '{
    for (i=1;i<NF;i+=2) {
        sum[$i]+=$(i+1)
    }
    ofs = ""
    for (key in sum) {
        printf "%s%s %d)", ofs, key, sum[key]
        delete sum[key]
        ofs = OFS
    }
    print ""
}' file
(X2 99) (X3 39) (X1 58)
(X3 11) (X1 30)

如果您关心字段的顺序,可以通过各种方式保留原始订单...

答案 1 :(得分:3)

你在这里:

echo '(X1 55) (X2 99) (X3 29) (X1 3) (X3 10)' | sed 's/[()]//g' | awk '{for( i=1; i<NF; i+=2) a[$i]+=$(i+1);} {for (keys in a ) print keys, a[keys];}'

输出:

X1 58
X2 99
X3 39

我认为这已足够接近了?

答案 2 :(得分:0)

我应该操纵FSRS来紧密匹配数据。除非您使用gawk >= 4.0并设置PROCINFO["sorted_in"]来指定它们的遍历方法,否则awk的数组遍历是随机的。

$ awk '
    NF{ x[$1] += $2 }
    2==NF{
        for (i in x) { printf "%s(%s %s)", sep, i, x[i]; sep = " "; }
        print "";
        split("",x); sep = "";
    }
    ' RS='[\\n\\(]' FS='[ \\n]' /tmp/file.txt
(X1 58)  (X2 99)  (X3 39)
(X1 30)  (X3 11)