Question

I have a file with values such as:

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

Is there a way to add the values by the Xn names in each row:

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

I'm not sure which is best to use, awk, sed or...? I tried this:

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

196
41

It obviously sums all values together, so maybe it's a bit more complex.

Était-ce utile?

La solution

$ 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)

If you care about the order of the fields, there's various ways to keep the original order...

Autres conseils

Here you are:

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];}'

output:

X1 58
X2 99
X3 39

I think that's close enough?

I'd go with manipulating FS and RS to closely match the data. awk's array traversal is random unless you are using gawk >= 4.0 and set PROCINFO["sorted_in"] to specify they method of traversal.

$ 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)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top