grep string where next line does not contain string

You can use perl compatible regular expressions grep:

$ pcregrep -M '(searchString.*\n)(?!.*excludeString)' file
foo2 searchString bar
foo3 searchString bar
foo4 searchString bar

It searches searchString followed by any char ., repeated zero or more times *, followed by new line \n only if there is not (?!) pattern .*excludeString next to it. Option -M is present in order to match multi lines.


With sed:

sed '/searchString/!d;$!N;/\n.*excludeString/!P;D' infile

How it works:

  • /searchString/!d deletes the line if it doesn't match searchString and reads in a new line, starting the command cycle over again (i.e. the remaining commands are no longer executed)
  • if the line matches searchString, sed executes $!N;/\n.*excludeString/!P;D - see HERE how it works; the difference is that here, it is looking for the pattern excludeString after the \newline character so that a line matching both searchString and excludeString is still printed if it's not followed by a line matching excludeString; if there was no line matching both searchString and excludeString (i.e. known input) then you could drop the \n.* part and run:
    sed '/searchString/!d;$!N;/excludeString/!P;D' infile