To find the lines that match each and everyone of a list of patterns, agrep
(the original one, now shipped with glimpse, not the unrelated one in the TRE regexp library) 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/'
Or with sed
:
sed -e '/pattern1/!d' -e '/pattern2/!d'
Or perl
:
perl -ne 'print if /pattern1/ && /pattern2/'
Please beware that all those will have different regular expression syntaxes.
The awk
/sed
/perl
ones don't reflect whether any line matched the patterns in their exit status. To so that you need:
awk '/pattern1/ && /pattern2/ {print; found = 1}
END {exit !found}'
perl -ne 'if (/pattern1/ && /pattern2/) {print; $found = 1}
END {exit !$found}'
Or pipe the command to grep '^'
.
For potentially gzip-compressed files, you can use zgrep
which is generally a shell script wrapper around grep
, and use one of the grep
solutions above (not the ast-open one as that grep
implementation cannot be use by zgrep
) or you could use the PerlIO::gzip
module of perl
which can transparently uncompress files upon input:
perl -MPerlIO::gzip -Mopen='IN,gzip(autopop)' -ne '
print "$ARGV:$_" if /pattern1/ && /pattern2/' -- *.gz
(which if the files are small enough at least is even going to be more efficient than zgrep
as the decompression is done internally without having to run gunzip
for each file).
foo
and lines that containbar
" see using grep for multiple search patterns – enharmonic Mar 27 '20 at 17:17