cyclONEnation cyclONEnation - 1 month ago 8
Linux Question

Start and Stop Printing with 2 keywords in AWK

I have this ...

#!/usr/bin/awk -f
{if($1 == "#BEGIN") while($1 != "#END") print}


what I want the output to print is this when the input file is read in.

This is a simple test file.
#BEGIN
These lines should be extracted by our script.

Everything here will be copied.
#END
That should be all.
#BEGIN
Nothing from here.
#END
user$ extract.awk test1.txt
These lines should be extracted by our script.

Everything here will be copied.
user$


Only the first set of BEGIN and END text will be copied. Not sure on how the best way to do this is.

Answer

Using awk

Try:

$ awk 'f && /^#END/{exit} f{print} /^#BEGIN/{f=1}' test1.txt
These lines should be extracted by our script.

Everything here will be copied.

How it works:

  • f && /^#END/{exit}

    If f is nonzero and this line starts with #END, exit.

  • f{print}

    If variable f is nonzero, print this line.

  • /^#BEGIN/{f=1}

    If this line starts with #BEGIN, set variable f to one.

Using sed

$ sed -n '/^#BEGIN/{n; :a; /^#END/q; p; n; ba}' test1.txt 
These lines should be extracted by our script.

Everything here will be copied.

How it works:

  • /^#BEGIN/{...}

    When we reach a line starting with #BEGIN, execute the commands in curly braces. These commands are:

  • n

    Read in the next line.

  • :a

    Define label a.

  • /^#END/q

    If the current line starts with #END, then quit.

  • p

    Print this line.

  • n

    Read in the next line.

  • ba

    Branch (jump) back to label a.

Making the awk command into a script

Method 1

Create this script file:

$ cat script1
#!/bin/sh
awk 'f && /^#END/{exit} f{print} /^#BEGIN/{f=1}' "$1"  

This can be executed as:

$ bash script1 test1.txt 
These lines should be extracted by our script.

Everything here will be copied.

Method 2

Create this file:

$ cat script.awk
#!/usr/bin/awk -f
f && /^#END/{exit}
f{print}
/^#BEGIN/{f=1}

Run it as follows:

$ awk -f script.awk test1.txt 
These lines should be extracted by our script.

Everything here will be copied.

Or, make it executable:

$ chmod +x script.awk

And execute it:

$ ./script.awk test1.txt
These lines should be extracted by our script.

Everything here will be copied.

Making the awk script into a shell function

$ extract() { awk 'f && /^#END/{exit} f{print} /^#BEGIN/{f=1}' "$1"; }
$ extract test1.txt 
These lines should be extracted by our script.

Everything here will be copied.