How to print lines only if next line is not matching using sed or awk

Viewed 112

I have the below pattern in the logs file where a "Starts" is finished with a "Ends" in the next line. I am looking to print only if the next line pattern is not matched with a "Ends", i:e to print all the Starts which are not ended.

$ egrep AccountResource testlog.txt|egrep "Starts|Ends"
05:20:34.949 INFO  c.b.h.r.rest.Account - AccountResource for account:12345 - Starts
05:20:45.863 INFO  c.b.h.r.rest.Account - AccountResource () - Ends
05:20:46.274 INFO  c.b.h.r.rest.Account - AccountResource for account:12345 - Starts
05:20:46.360 INFO  c.b.h.r.rest.Account - AccountResource () - Ends
05:22:21.703 INFO  c.b.h.r.rest.Account - AccountResource for account:12345 - Starts
05:22:22.680 INFO  c.b.h.r.rest.Account - AccountResource for account:5678 - Starts
05:52:48.578 INFO  c.b.h.r.rest.Account - AccountResource for account:5678 - Starts
05:52:50.673 INFO  c.b.h.r.rest.Account - AccountResource () - Ends
05:52:50.937 INFO  c.b.h.r.rest.Account - AccountResource for account:12345 - Starts
05:52:50.977 INFO  c.b.h.r.rest.Account - AccountResource () - Ends
06:09:35.951 INFO  c.b.h.r.rest.Account - AccountResource for account:5678 - Starts
06:09:36.409 INFO  c.b.h.r.rest.Account - AccountResource () - Ends
06:09:36.690 INFO  c.b.h.r.rest.Account - AccountResource for account:5678 - Starts
06:09:36.720 INFO  c.b.h.r.rest.Account - AccountResource () - Ends

below is expected output

05:22:21.703 INFO  c.b.h.r.rest.Account - AccountResource for account:12345 - Starts
05:22:22.680 INFO  c.b.h.r.rest.Account - AccountResource for account:5678 - Starts
3 Answers

You may use a single awk for this job:

awk '!/AccountResource/{next} NR == nl && $NF!="Ends" {print p} $NF=="Starts" {p=$0; nl=NR+1}' testlog.txt

05:22:21.703 INFO  c.b.h.r.rest.Account - AccountResource for account:12345 - Starts
05:22:22.680 INFO  c.b.h.r.rest.Account - AccountResource for account:5678 - Starts

A more readable version:

awk '
!/AccountResource/ {next}
NR == nl && $NF != "Ends" {print p}
$NF == "Starts" {
   p = $0
   nl = NR+1
}' testlog.txt

This might work for you (GNU sed):

sed 'N;/Starts\n.*Ends$/d;P;D' file

Process two lines at a time.

If the first ends in Starts and the second ends in Ends, delete both.

Otherwise print/delete the first and repeat.

With your shown samples, please try following awk code.

awk '
!/AccountResource/{ next      }
/AccountResource.*Starts$/{
  if(found && val){ print val }
  found=1
  val=$0
}
/AccountResource.*Ends$/{
  found=0
  val=""
}
'  Input_file

Explanation: Adding detailed explanation for above.

awk '                              ##Starting awk program from here.
!/AccountResource/{ next      }    ##If a line does not contain AccountResource move cursor to next line.
/AccountResource.*Starts$/{        ##Checking condition if line contains AccountResource and ends with Starts then do following.
  if(found && val){ print val }    ##If found and val both are SET then print val.
  found=1                          ##Setting found to 1 here.
  val=$0                           ##Setting val to current line here.
}
/AccountResource.*Ends$/{          ##Checking condition if line contains AccountResource and ends with Ends then do following.
  found=0                          ##Set found to 0 here.
  val=""                           ##Nullify val here.
}
'  Input_file                      ##Mentioning Input_file name here.
Related