سؤال

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.

هل كانت مفيدة؟

المحلول

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

نصائح أخرى

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)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top