How to run grep with multiple AND patterns?

  • I would like to get the multi pattern match with implicit AND between patterns, i.e. equivalent to running several greps in a sequence:

    grep pattern1 | grep pattern2 | ...
    

    So how to convert it to something like?

    grep pattern1 & pattern2 & pattern3
    

    I would like to use single grep because I am building arguments dynamically, so everything has to fit in one string. Using filter is system feature, not grep, so it is not an argument for it.


    Don't confuse this question with:

    grep "pattern1\|pattern2\|..."
    

    This is an OR multi pattern match.

    If you're looking for the grep syntax for "find lines that contain `foo` and lines that contain `bar`" see using grep for multiple search patterns

  • agrep can do it with this syntax:

    agrep 'pattern1;pattern2'
    

    With GNU grep, when built with PCRE support, you can do:

    grep -P '^(?=.*pattern1)(?=.*pattern2)'
    

    With ast grep:

    grep -X '.*pattern1.*&.*pattern2.*'
    

    (adding .*s as <x>&<y> matches strings that match both <x> and <y> exactly, a&b would never match as there's no such string that can be both a and b at the same time).

    If the patterns don't overlap, you may also be able to do:

    grep -e 'pattern1.*pattern2' -e 'pattern2.*pattern1'
    

    The best portable way is probably with awk as already mentioned:

    awk '/pattern1/ && /pattern2/'
    

    With sed:

    sed -e '/pattern1/!d' -e '/pattern2/!d'
    

    Please beware that all those will have different regular expression syntax.

    The `agrep` syntax is not working for me... which version was it introduced in?

    @Raman 2.04 from 1992 already had it. I've no reason to believe it wasn't there from the start. Newer (after 1992) versions of `agrep` can be found included with glimpse/webglimpse. Possibly you have a different implementation. I had a mistake for the ast-grep version though, the option for _augmented regexps_ is `-X`, not `-A`.

    @StéphaneChazelas Thanks, I have `agrep` 0.8.0 on Fedora 23. This appears to be a different `agrep` than the one you reference.

    @Raman, yours sounds like TRE `agrep`.

    @StéphaneChazelas Indeed it is. Too bad Fedora doesn't have the `agrep` you are referring to, out of the box.

    `awk '/pattern1/ && /pattern2/'` is good, but how do i calculate count for this?

    @Techiee, you mean the count of lines that match either pattern or the count of occurrences of each pattern? In any case, it seems it would be a different question.

    @StéphaneChazelas, Right now `awk '/pattern1/ && /pattern2/'` is printing all the lines, i want the print the count of such lines. Can you help? Thanks

    @StéphaneChazelas: I got it, `awk '/pattern1/ && /pattern2/' filename | wc -l` will give me desired output.

    @Techiee, or just `awk '/p1/ && /p2/ {n++}; END {print 0+n}'`

    The `awk` solution doesn't work for me on Cygwin. Looks like it is but checking the process shows that it's doing nothing, no CPU usage at all.

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM