Bash grep regexp - excluding subpattern

I have a script written in bash with one specific grep command that I need to change.

As a rule, I have two templates: A and B. There is a text file that can contain lines with all possible combinations of these templates, namely: "xxxAxxx", "xxxBxxx", "xxxAxxxBxxx", "xxxxxx", where "x "- any characters.

I need to match ALL APART strings from those that contain ONLY "A".

At the moment, this is done using < grep -v (A)", but this is a false track, as it also excludes lines with" xxxAxxxBxxx "- which are suitable for me. That's why it needs to be modified. :)

The tricky part is that this grep lies in the middle of the multiply-piped command with many other greps, seds, and awks inside. Thus, creating a more reasonable template would be a better solution. Others can cause extra work to change other commands and even affect other parts of the code.

Therefore, the question arises: is it possible to match the template and exclude the subpattern in one grep, but allow them to appear as in one line?

Example: A file contains the following lines:

fooTHISfoo
fooTHISfooTHATfoo
fooTHATfoo
foofoo

and I need to match

fooTHISfooTHATfoo
fooTHATfoo
foofoo

line with "THIS" is not allowed.

+4
source share
4 answers

You can use this awk command:

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

Or by changing the boolean expression:

awk '!/THIS/ || /THAT/' file
fooTHISfooTHATfoo
fooTHATfoo
foofoo
+3
source

, B, A. , , A, B. sed:

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

:

sed '/THIS/{/THAT/!d}' file
+2

The trick is for grep only. However, replace this with an awk call: Filter the lines with "A" if "B" does not exist

echo "xxxAxxx
xxxBxxx
xxxAxxxBxxx
xxxBxxxAxxx
xxxxxx" | awk '!/A/ || /B/'
xxxBxxx
xxxAxxxBxxx
xxxBxxxAxxx
xxxxxx
+1
source

grep. Uses perl regexp ( -P) for Lookaheads (see if not, some explanation here ).

grep -Pv '^((?!THAT).)*THIS((?!THAT).)*$' file
+1
source

Source: https://habr.com/ru/post/1608826/


All Articles