2

How can we use grep to get line(s) containing a group of words, while the order of words is not important, although line(s) should contain all words mentioned in search?

I have done that with phasing the search (with piping, saving the outputs in temporary files, and searching again), but I'd like to know if I can do that in one attempt.

Here is a sample; I want to search in the lines below for lines containing sample, words, list:

it's a sample test file for a list of words.
list of words without a specific order, it's a sample.
line with no search keyword here.
list the sample files.
something completely different.

And get this result:

it's a sample test file for a list of words.
list of words without a specific order, it's a sample.
8
  • Are the sentences on separate lines, can OP confirm this? Aug 23, 2018 at 14:20
  • 1
    This grep -e words -e sample -e list newfile works as well Aug 23, 2018 at 14:24
  • 1
    Hi George. Yes, each sentence is on a separate line. Aug 23, 2018 at 14:27
  • 2
    Probably awk better fits here.
    – PerlDuck
    Aug 23, 2018 at 14:34
  • 3
    @PerlDuck I agree, much easier. awk '(/sample/ && /words/ && /list/)' samplefile
    – Terrance
    Aug 23, 2018 at 14:43

2 Answers 2

4

The easy way is with multiple calls to grep:

grep sample testfile.txt | grep words | grep list

A demonstration:

echo -e "it's a sample test file for a list of words.\nlist of words without a specific order, it's a sample. \nline with no search keyword here. \nlist the sample words. \nsomething completely different." | grep sample | grep words | grep list
it's a sample test file for a list of words.
list of words without a specific order, it's a sample. 
list the sample words. 
2
  • yes, this works as I've mentioned, but i'm looking for a one-line-solution. Although sometimes it's better to do things the easy way. thanks :) Aug 23, 2018 at 18:11
  • grep -e also selects lines which have only two words (not all the words). Maybe I should try awk instead of grep, it works fine. Thank you all Aug 23, 2018 at 18:18
4

You can use lookaheads with Perl-regex (-P):

grep -P '(?=.*list)(?=.*words)(?=.*sample)'

Example:

echo "it's a sample test file for a list of words.
list of words without a specific order, it's a sample.
line with no search keyword here.
list the sample words.
sample line with only two of the keywords inside.
something completely different." \
| grep -P '(?=.*list)(?=.*words)(?=.*sample)'

it's a sample test file for a list of words.
list of words without a specific order, it's a sample.
list the sample words.

(via)


With agrep (sudo apt install agrep) you can chain multiple patterns:

agrep "sample;words;list"

(via)

Not the answer you're looking for? Browse other questions tagged or ask your own question.