Is there a grep-like utility that will enable me to do grep searches with logic operators. I want to be able to nest and combine the logical constructs freely. For example, stuff like this should be possible:

grep (term1 && term2) || (term1 && (term3 xor term4)) *

I realize this can be done with vanilla grep and additional bash scripting, but my goal here is to avoid having to do that.


There are lot of ways to use grep with logical operators.

  1. Use \| to separate multiple patterns for the OR condition.

    Example: grep 'pattern1\|pattern2' filename

  2. Use the -E option to send multiple patterns for the OR condition.

    Example: grep -E 'pattern1|pattern2' filename

  3. Using a single -e matches only one pattern, but using multiple -e option matches more than one pattern.

    Example: grep -e pattern1 -e pattern2 filename

  4. grep -v can simulate the NOT operation.

  5. There is no AND operator in grep, but you can brute-force simulate AND by using the -E option.

    Example : grep -E 'pattern1.*pattern2|pattern2.*pattern1' filename

    The above example will match all the lines that contain both pattern1 and pattern2 in either order.)

  • 2
    -E is not quite equivalent to && due to the fact that it is order-sensitive
    – iruvar
    Jan 5 '15 at 13:58
  • 3
    grep foo | grep bar is a more general way to do AND.
    – Kenster
    Jan 5 '15 at 15:43
  • 2
    +1 for clearly explaining that there isn't a real "AND" operator, and that the best we can do is simulate a hack using an OR structure. This will of course get unwieldy with more than 3 terms, but for two terms it works well. Apr 20 '17 at 15:57
  • grep -c -e MATCH1 -e MATCH2 is great when you are interested in filename counts.
    – andrej
    Jul 10 '19 at 11:26

With awk, as with perl, you'll have to wrap terms in //, but it can be done:

awk '(/term1/ && /term2/) || (/term1/ && xor(/term3/, /term4/))' 

You could use perl:

perl -wne 'print if (/term1/ && /term2/) || (/term1/ && (/term3/ xor /term4/))'

Where the switches are as follows:

-w turns on warnings
-n runs perl against each line of input (looping)
-e executes perl passed in the command line

GNU grep allows perl regex, so we can do this to find lines containing both word1 and word2.

grep -P '(?=.*word1)(?=.*word2)' filename

(see this post) for more details.

  • That helped, thanks!
    – Ferit
    Feb 11 at 13:26
sed '/term1/!d;/term2/b' -e '/term3/!d;/term4/d' *

I believe that accomplishes what you're trying to do. It deletes from output any line which doesn't match term1, it branches out of the script (and so autoprints) any line that remains and that matches term2, and for lines that remain it deletes any which do not match term3 and from those any that do match term4.

sed scripts are evaluated in order, and all tests are boolean, so any actions resulting from a test are going to directly affect the behavior of any following actions.


I use to chain grep commands to achieve a logical AND:

grep expr1 filename | grep expr2

I believe it is pretty straightforward, Unix-like and elegant.

Then you can combine (as @Tushi thoroughly explained) with the -E option for OR-ing and -v for negating.

Your specific example is pretty nasty and probably would benefit from some more powerful utility (see @muru's answer).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy