-1

I have asked similar question here, but this one I feel is more complicated than that so, asking in different post.

foo foo foo foo foo
Import blash blah blah
foo foo foo foo foo 
blah blah blah blah 
Error loading file
blah blah blah blah
blah blah blah blah
query run ends
foo foo foo foo
Import blash blah blah
foo foo foo foo foo 
foo foo foo foo foo 
Exception occurred
blah blah blah blah
blah blah blah blah
query run ends
Import blash blah blah
foo foo foo foo foo 
foo foo foo foo foo 
query run ends

In the pattern similar to above, I want to grep all the contents between all Import and ends if Error or Exception exist in between them. And in that process I want to exclude those Import & ends combination which doesn't have any Error or Exception string.

Note:

The lines between Import & ends strings are not constant, it may vary.

Expected:

Import blash blah blah
foo foo foo foo foo 
blah blah blah blah 
Error loading file
blah blah blah blah
blah blah blah blah
query run ends
Import blash blah blah
foo foo foo foo foo 
foo foo foo foo foo 
Exception occurred
blah blah blah blah
blah blah blah blah
query run ends
Praveen
  • 31
  • 8

4 Answers4

0

If your data does not contain any blank lines, you could do:

nl='
'; sed -n -e "/Import/,/ends/{/ends/s/\$/\\$nl/; p;}" input |
     awk /Exception\|Error/ RS=

This is just pre-processing the data to remove all lines that do not appear between Import and ends, and adds a blank line between records. With the data in that format, the awk solution is trivial. (I don't normally condone piping sed to awk, but it's not unusual to do that sort of thing when each step has a different record separator)

If your data does potentially have blank lines, you could pre and post process with something like:

nl='
'; sed -n -e '/^$/s/^/BLANK LINE/' -e "/Import/,/ends/{/ends/s/\$/\\$nl/; p;}" input |
     awk /Exception\|Error/ RS= | sed 's/^BLANK LINE$//'

Note, there are cleaner ways to insert a blank line. Also, there's is a certain fragility in pre/post processing like this; namely, you need to pick a sentinel (the string "BLANK LINE") as some string that does not appear in your input.

William Pursell
  • 204,365
  • 48
  • 270
  • 300
0

The same sed as yesterday with one more condition.

sed '/^Import/!d;:A;N;/\nImport/{h;s/.*\n//;bA};/ends$/!bA;h;s/\nException//;tB;s/\nError//;tB;d;:B;x' infile
ctac_
  • 2,413
  • 2
  • 7
  • 17
0

using awk to print from "Import" to "ends" when this block contains "Error" or "Exception".

awk '/Import/,/ends/                 {s = s "\n" $0} 
     /ends/ && s ~ /Error|Exception/ {print s; s=""}' file

output for the example input.

Import blash blah blah
foo foo foo foo foo 
blah blah blah blah 
Error loading file
blah blah blah blah
blah blah blah blah
query run ends

Import blash blah blah
foo foo foo foo foo 
foo foo foo foo foo 
Exception occurred
blah blah blah blah
blah blah blah blah
query run ends
thanasisp
  • 5,855
  • 3
  • 14
  • 31
-1

GNU awk solution (assuming Import keyword doesn't occur within intermediate text):

awk -v RS='Import' '$0~/\<(Error|Exception)/{ printf "%s%s",RS,$0 }' file
  • -v RS='Import' - treat Import keyword as record separator

The output:

Import blash blah blah
foo foo foo foo foo 
blah blah blah blah 
Error loading file
blah blah blah blah
blah blah blah blah
query run ends
Import blash blah blah
foo foo foo foo foo 
foo foo foo foo foo 
Exception occurred
blah blah blah blah
blah blah blah blah
query run ends
RomanPerekhrest
  • 88,541
  • 4
  • 65
  • 105
  • 1
    thanks @RomanPerekhrest , is it possible to put 'ends' keyword too as RS which will be helpful if logs pattern contain some other records between 'ends' and next 'Import'?? – Praveen Nov 22 '17 at 12:12
  • updated the the original post too with change in pattern – Praveen Nov 22 '17 at 12:32
  • 1
    Note that using more than a single character for RS is a gnu awk extension and will not work in all implementations of awk. – William Pursell Nov 22 '17 at 12:38