简体   繁体   中英

Linux grep, how can I display lines that don't contain word 1 and word 2 but still display the lines that have both words in them

I need some help with displaying all lines that don't contain word1 or word2 but lines that contain both of them have to be shown.

Example:

aaaa bbbb cccc
bbbb bbbb bbbb
cccc cccc cccc
dddd dddd aaaa

if word1 = aaaa and word2 = bbbb then output should be:

aaaa bbbb cccc
cccc cccc cccc

Tried

grep -Ewv "word1/word2" file.txt 

but this shows only lines that don't contain them, it doesn't show lines containing both

I need to do this with grep command, forgot to mention this

Grep version of both or none of each:

grep -v -P '((?=.*aaaa)(?!.*bbbb))|((?=.*bbbb)(?!.*aaaa))'

But please do not use grep in this case. Negative and positive look ahead can easily lead to Catastrophic Backtracking

GNU grep knows Perl compatible regular expression (PCRE) syntax (option -P ). This thing is still called a "regular" expression, although it not regular anymore. Other people are more explicit and call backtracking irregular expressions.

How it works:

(?=.*aaaa) matches aaaa anywhere in the line, but does not move the cursor. After the match the next search starts at the beginning of the line.

(?..*bbbb) matches when no bbbb is in the line and does not move the cursor either.

Both together matches lines, which include aaaa but do not include bbbb .

This is one of the cases you want to exclude, from your search results. The second behind the or condition ( | ) is the other one you want to exclude: any bbbb without a aaaa .

With the above, you have defined, what you do not want. Next use -v to invert the search to get what you want.

预期输出

Bash version of both or none of each:

#! /bin/bash

word1=${1:-aaaa}
word2=${2:-bbbb}

while read -r line; do
  if [[ $line =~ $word1 ]]; then
    if [[ $line =~ $word2 ]]; then
      printf "%s\n" "$line"
    fi
  else
    if [[ $line =~ $word2 ]]; then
      :
    else
      printf "%s\n" "$line"
    fi
  fi
done

In my opinion, the simplest way (even though possibly not the fastest) is to find separately the lines that contain neither word and the lines that contain both words, and to concatenate the results. For example (assuming file.txt is a text file in directory test , and I pass the input values as environment variables for generality - and we are only looking for full words, not word fragments):

[mathguy@localhost test]$ more file.txt
aaaa bbbb cccc
bbbb bbbb bbbb
cccc cccc cccc
dddd dddd aaaa



[mathguy@localhost test]$ word1=aaaa
[mathguy@localhost test]$ word2=bbbb

[mathguy@localhost test]$ ( grep "\b$word1\b" file.txt | grep "\b$word2\b" ; \
>  grep -v "\b$word1\b" file.txt | grep -v "\b$word2\b" ) | cat
aaaa bbbb cccc
cccc cccc cccc

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM