Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bash grep regexp - excluding subpattern

Tags:

regex

grep

bash

I have a script written in bash, with one particular grep command I need to modify.

Generally I have two patterns: A & B. There is a textfile that can contain lines with all possible combinations of those patterns, that is: "xxxAxxx", "xxxBxxx", "xxxAxxxBxxx", "xxxxxx", where "x" are any characters.

I need to match ALL lines APART FROM the ones containing ONLY "A".

At the moment, it is done with "grep -v (A)", but this is a false track, as this would exclude also lines with "xxxAxxxBxxx" - which are OK for me. This is why it needs modification. :)

The tricky part is that this one grep lies in the middle of a 'multiply-piped' command with many other greps, seds and awks inside. Thus forming a smarter pattern would be the best solution. Others would cause much additional work on changing other commands there, and even would impact another parts of the code.

Therefore, the question is: is there a possibility to match pattern and exclude a subpattern in one grep, but allow them to appear both in one line?

Example: A file contains those lines:

fooTHISfoo
fooTHISfooTHATfoo
fooTHATfoo
foofoo

and I need to match

fooTHISfooTHATfoo
fooTHATfoo
foofoo

a line with "THIS" is not allowed.

like image 392
ptr92zet Avatar asked Mar 15 '23 16:03

ptr92zet


2 Answers

You can use this awk command:

awk '!(/THIS/ && !/THAT/)' file
fooTHISfooTHATfoo
fooTHATfoo
foofoo

Or by reversing the boolean expression:

awk '!/THIS/ || /THAT/' file
fooTHISfooTHATfoo
fooTHATfoo
foofoo
like image 104
anubhava Avatar answered Mar 17 '23 05:03

anubhava


You want to match lines that contain B, or don't contain A. Equivalently, to delete lines containing A and not B. You could do this in sed:

sed -e '/A/{;/B/!d}'

Or in this particular case:

sed '/THIS/{/THAT/!d}' file
like image 28
Toby Speight Avatar answered Mar 17 '23 06:03

Toby Speight