Awk "if" operator

I have a file

foo -- bar 

I want only the lines above the separator. I struggled with this for too long and tried several options. My one liner:

 echo -e "foo\n-- \nbar" | gawk -vx=0 -- '/^--\ / { x++ } ; IF (x==0) {print} ' 

This should print only "foo", but I get all the file output. If I go to print x, I get

 0 1 1 

I cannot force make awk to conditionally print a string based on the value of x. I know that I am missing something simple.

+4
source share
4 answers

Try to do this:

 echo -e "foo\n-- \nbar" | awk '/^--/{exit}1' 

EXPLANATION

  • /^--/ is a regular expression matching the line at the beginning of the current line
  • {} the part is true if the condition is true (previous regular expression)
  • 1 is like {print} : by default, awk prints to STDOUT if the condition is true. While 1 true for awk, it prints the current line.

Team decomposition:

 echo -e "foo\n-- \nbar" | awk ' { if (/^--/) { exit } else { print } } ' 

Alternative decomposition:

 echo -e "foo\n-- \nbar" | awk '(/^--/) { exit } { print }' 

This emphasizes that there are two rules for the operation of the template; one with an explicit pattern and exit action; another with an implicit pattern and print action. A.

+4
source

If you like sed better:

 sed -n '/^--$/q;p' file.txt 

Explanation: sed reads the file line by line. If sed finds the ^--$ pattern (that is, a string containing exactly -- ), it exits ( q command); otherwise, sed displays the contents of this string (using the p command). Note that sed was started with the -n option, i.e. it does not display anything unless explicitly specified with the p command. Since sed terminates when a separator -- found -- (that is, before the p command), this separator will not be printed.

The good thing about sed is that it is faster than awk for this task.

Change As Glenn Jackman notes in a comment, with GNU sed you can use:

 sed '/^--$/Q' file.txt 

(I was not on a sed machine with the q command when I answered). Thanks, Glenn.

+2
source

Your original script was on the right lines, but too complicated:

 echo -e "foo\n-- \nbar" | gawk '/^--\ / { x++ } { if (x==0) print}' 

Variables are automatically created and nullified by awk (so you don't need -vx=0 , etc.). The code "spot the double dash" was fine. A half-column is not needed (at best). IF (x == 0) {print} looks weird. awk on Mac OS X 10.7.5 accepts this, but I'm not sure what it does. The replace action for each line also checks if x zero before printing.

Personally, I would use sed for this:

 echo -e "foo\n-- \nbar" | sed '/^--/q' 

Committing my sed command as gniourf_gniourf suggests :

 echo -e "foo\n-- \nbar" | sed -n '/^--/q;p' 

You can imitate this in awk with the sputnick command in the answer.

 echo -e "foo\n-- \nbar" | awk '/^--/ {exit} 1' 

1 corresponds to each line (it is always true) and triggers the default action, which is "print $ 0". You can also write:

 echo -e "foo\n-- \nbar" | awk '/^--/ {exit} {print}' 
+1
source

In GNU awk, you can simply set the record separator as a string containing only "-", and then just print the first record:

 $ gawk -v RS='\n--\n' 'NR==1' file foo 

or if performance is a problem:

 $ gawk -v RS='\n--\n' 'NR==1{print;exit}' file foo 

this way you can improve the script later to print any other entry you might want:

 $ cat file the quick -- brown fox -- jumped $ $ gawk -v RS='\n--\n' 'NR==1' file the quick $ gawk -v RS='\n--\n' 'NR==2' file brown fox $ gawk -v RS='\n--\n' 'NR==3' file jumped 
+1
source

All Articles