1

My file is written like:

apples,oranges,berries,cherries

beer,wine,shots

chocolate,icecream,cake,muffins

cherries,guacamole,lychee

I need to output the second to last word in lines that contain the word cherries using awk:

    I want it to print:

food: berries, guacamole

cherries appeared: 0/2 times

I currently have:

/cherries/

BEGIN {print "food:";}

{for (NR in a) {

FS=",";

printf($(NF-1));j++;

if((NF-1)=="cherries"){$i++;}

}

}
END {print "cherries appeared" i/j "times"}

What happens is it just prints every line that has cherries in it (the entire line) and $i$ comes out with a value of 0, so here it would print:

food: apples,oranges,berries,cherriescherries,guacamole,lychee

cherries appeared: nantimes

  • "the second to last word in lines that contain the word cherries" is inconsistent with your example output: That is the second to last word of every line. – Hauke Laging Feb 28 '14 at 17:07
  • oops you are right, sorry!!!! @HaukeLaging – WaffleMonster Feb 28 '14 at 17:11
  • This is very hard to understand. Could you please fix the formatting? See here for help. Why should it print that cherries appeared 0 times? You have it twice in your file. Where do you define the a array? Why are you using NR in that loop? – terdon Feb 28 '14 at 17:23
1
awk -F, 'BEGIN {printf "%s","food: ";}; '\
'/cherries/ {if (matches>0) printf "%s",", "; printf "%s",$(NF-1); matches++;};'\
' END {print "";print "cherries appeared " matches "/" NR " times"}'

leads to this output:

food: berries, guacamole
cherries appeared 2/4 times
  • How is this printing the second to last word of every line containing cherries? @Hauke Laging – WaffleMonster Feb 28 '14 at 17:02
  • @WaffleMonster It doesn't. It does that how I understood the task: everything from the second word up to the last word per line. What you need is even easier... – Hauke Laging Feb 28 '14 at 17:05
  • @WaffleMonster Like what? It works here; I have added the output I get. – Hauke Laging Feb 28 '14 at 17:16
  • Maybe my problem is I have to make the whole file an awk file so I have to alter it a bit... also, I needed food: to appear before berries and guacamole, so they can all be on the same line. What I have is: #! /usr/bin/awk -f /cherries/ BEGIN{print "food: "} {printf$(NF-1);matches++;}; END{print "cherries appeared "matches "/" NR " times"} @HaukeLaging – WaffleMonster Feb 28 '14 at 17:19
  • @WaffleMonster The awk file thing seems crazy to me. However, the output is correct now. – Hauke Laging Feb 28 '14 at 17:37
1

Do you want to count the number of times or the number of lines in which cherries appeared?

awk -F, '$0~k{s=s (s?", ":x) $(NF-1); t+=gsub(k,x)}
         END{printf "food: %s\n%s appeared %d/%d times\n", s, k, t, NR}
        ' k=cherries file

or

awk -F, '$0~k{s=s (s?", ":x) $(NF-1); t++}
         END{printf "food: %s\n%s appeared in %d/%d lines\n", s, k, t, NR}
        ' k=cherries file
0

I think what you want is

$ awk -F, 'BEGIN{ORS=",";printf "food: "} 
          /cherries/{print $(NF-1); matches++;}; 
          END{printf "\ncherries appeared "matches "/" NR " times\n"}' file 
food: berries,guacamole,
cherries appeared 2/7 times

Note that your file is double spaced so the number of lines includes the blank ones. To avoid this, use

$ awk -F, 'BEGIN{ORS=",";printf "food: "} 
           /./{k++} 
           /cherries/{print $(NF-1); matches++;};
          END{printf "\ncherries appeared matches /" k " times\n"}' file
food: berries,guacamole,
cherries appeared matches /4 times

-F "," is equivalent to FS=",". ORS is the output record separator which is also set to , for ease of printing. The downside is that it adds an extra , at the end of the food: line but you can remove that by piping through | sed 's/,$//'. Your main issue was that awk's print, prints whatever you give it followed by the value of ORS which is a newline by default.

I don't understand what you mean by cherries being the penultimate field since that is never the case in your example.

0

Another way:

awk -F, 'BEGIN{printf "food: "}
         /cherries/ {printf $(NF-1) FS; count++}
         END{printf "\ncherries appeared %d/%d times\n", count, NR}' file
  • BEGIN prints the text header.
  • /cherries/ {printf $(NF-1) FS; count++} keeps printing the second last word on lines containing cherries. In that case, it also keeps track of how many lines match.
  • END prints the summary.

For your file, it returns:

$ awk -F, 'BEGIN{printf "food: "} /cherries/ {printf $(NF-1) FS; count++} END{printf "\ncherries appeared %d/%d times\n", count, NR}' file
food: berries,guacamole,
cherries appeared 2/4 times

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.