2

I have this input:

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

and I want output like this:

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

I am trying to do it with awk command. My code looks like this:

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


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

I to compare duplicates in second collumn and sum the numbers.

6
  • The only problem is with Susy. Because my code will output this Susy: oranges 5 oranges 12
    – Mafi
    Commented May 17, 2016 at 19:18
  • If you could use 2-dimensional arrays, indexed by name and fruit name, how would you solve it? Commented May 17, 2016 at 19:28
  • { lines[$1,$2] = (lines[$1,$2] ? lines[$1,$2] "\n " $2 " " $3 : $1 ":\n " $2 " " $3) } END { for (line in lines) print lines[line,line] }
    – Mafi
    Commented May 17, 2016 at 19:44
  • Would this work?
    – Mafi
    Commented May 17, 2016 at 19:45
  • Think of a way to sum up the number of each type of fruit that each person has. You can use the + or += operator. Commented May 17, 2016 at 19:47

2 Answers 2

3

Using GNU awk, which has arrays of arrays (may require 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]
        }
    }
'
1

If you don't mind having the output sorted, you can keep track of the current person and the current fruit, and sum until either changes:

#!/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
}

Feed this with sort -k1,1 -k2,2:

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .