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

3
  • "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. Feb 28, 2014 at 17:07
  • oops you are right, sorry!!!! @HaukeLaging Feb 28, 2014 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, 2014 at 17:23

4 Answers 4

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
5
  • How is this printing the second to last word of every line containing cherries? @Hauke Laging Feb 28, 2014 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... Feb 28, 2014 at 17:05
  • @WaffleMonster Like what? It works here; I have added the output I get. Feb 28, 2014 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 Feb 28, 2014 at 17:19
  • @WaffleMonster The awk file thing seems crazy to me. However, the output is correct now. Feb 28, 2014 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

You must log in to answer this question.

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