Suche nach Duplikaten in der ersten und zweiten Spalte und summiere die Zahlen in der dritten Spalte

Suche nach Duplikaten in der ersten und zweiten Spalte und summiere die Zahlen in der dritten Spalte

Ich habe diese Eingabe:

Fred apples 20
Susy oranges 5
Mark watermellons 12
Robert pears 4
Robert oranges 17
Terry oranges 9

Lisa peaches 7
Susy oranges 12
Mark grapes 39
Anne mangoes 7
Greg pineapples 3
Oliver rockmellons 2
Betty limes 14

und ich möchte eine Ausgabe wie diese:

Anne:
         mangoes  7
Oliver:
     rockmellons  2
Greg:
      pineapples  3
Mark:
    watermellons 12
          grapes 39
Terry:
         oranges  9
Susy:
         oranges 17
Lisa:
         peaches  7
Fred:
          apples 20
Robert:
         oranges 17
           pears  4
Betty:
           limes 14

Ich versuche es mit dem awk-Befehl. Mein Code sieht folgendermaßen aus:

{
lines[$1] = (lines[$1] ? lines[$1] "\n  "   $2 " "  $3 :  $1 ":\n       " $2 " " $3)


    }
    END {
        for (line in lines) print lines[line]
        }

Ich vergleiche Duplikate in der zweiten Spalte und summiere die Zahlen.

Antwort1

Verwendung von GNU awk, das über Arrays von Arrays verfügt (erfordert möglicherweise Gawk Version 4)

gawk '
    NF  { n[$1][$2] += $3 }
    END {
        for (name in n) {
            print name ":"
            for (fruit in n[name]) 
                printf "%16s %2d\n", fruit, n[name][fruit]
        }
    }
'

Antwort2

Wenn es Ihnen nichts ausmacht, dass die Ausgabe sortiert ist, können Sie die aktuelle Person und die aktuelle Frucht im Auge behalten und summieren, bis sich eines davon ändert:

#!/usr/bin/awk -f

NF {
    if (who != $1) {
        if (count > 0) {
            printf "%16s %2d\n", fruit, count
        }
        who = $1
        printf "%s:\n", who
        fruit = ""
        count = 0
    }
    if (fruit != $2) {
        if (count > 0) {
            printf "%16s %2d\n", fruit, count
        }
        fruit = $2
        count = $3
    } else {
        count += $3
    }
}

END {
    printf "%16s %2d\n", fruit, count
}

Füttern Sie dies mit sort -k1,1 -k2,2:

sort -k1,1 -k2,2 file.txt | ./script.awk

verwandte Informationen