2

Have a contents in file similar to below- There are many lines between START & END and might have errors/warnings too. I want to filter out errors/warning lines between START & END and skip if doesn't have. Heading is varying with different names. But make logic of printing next line of START(should be heading)

START
Heading1
.......
errors
........
END

START
Heading2
........
........
........
END

START
Heading3
.......
errors
Warning...
END

Expected output below

Heading1
errors

Heading3
errors
Warning...

I have tried below , but this prints everything between START & END . I have to filter out errors too

awk '/START/,/END/' file
  • Im assuming you dont want to print START and END so.. grep -v -e "START" -e "END" -e "errors" input.txt – Goron Jun 19 at 5:30
  • Not Required START & END. Requirement is to print error lines followed by heading. I have edited ques related to heading part. Just not to get confuse. Thanks – Sin15 Jun 19 at 5:37
2

Try:

$ awk 'f{hdg=$0; f=0} /errors|warning/{if(hdg){print hdg; hdg=""}; print} /START/{f=1}' file
Heading1
errors
Heading3
errors

How it works

  • f{hdg=$0; f=0}

    If f is true (nonzero), then save the current line in the variable hdg and set f back to zero.

  • /errors|warning/{if(hdg){print hdg; hdg=""}; print}

    If the current line contains errors or warning, then, if the variable hdg is non-empty, print it. Also, print the current line.

  • /START/{f=1}

    If the current line contains START, then set variable f to one.

Multiline version

For those who prefer their commands spread over multiple lines:

awk '
   f {
      hdg=$0
      f=0
   }
   /errors|warning/{
      if(hdg){
         print hdg
         hdg=""
      }
      print
   }
   /START/{
      f=1
   }' file

Variation: Add a blank line before heading

If we want a blank line to separate the output:

$ awk 'f{hdg=$0; f=0} /errors|warning/{if(hdg){print nl hdg; hdg=""; nl="\n"}; print} /START/{f=1}' file
Heading1
errors

Heading3
errors

Variation: Ignore errors/warnings after an END line

$ awk 'f{hdg=$0; f=0} g && /errors|warning/{if(hdg){print nl hdg; hdg=""; nl="\n"}; print} /START/{f=1; g=1} /END/{g=0}' file
Heading1
errors

Heading3
errors

To make the above case insensitive (GNU awk):

awk 'BEGIN{IGNORECASE=1} f{hdg=$0; f=0} g && /errors|warning/{if(hdg){print nl hdg; hdg=""; nl="\n"}; print} /START/{f=1; g=1} /END/{g=0}' file
  • All Good John, I was trying to check the logic here. Also trying to add - 'BEGIN{IGNORECASE=1}' in the command to ignore error,ERROR....case sensitive – Sin15 Jun 19 at 6:36
  • @Sin15 Very good. And, yes, that should make the matches case-insensitive. – John1024 Jun 19 at 7:20

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.