Match two strings in one line with grep

439,812

Solution 1

You can use

grep 'string1' filename | grep 'string2'

Or

grep 'string1.*string2\|string2.*string1' filename

Solution 2

I think this is what you were looking for:

grep -E "string1|string2" filename

I think that answers like this:

grep 'string1.*string2\|string2.*string1' filename

only match the case where both are present, not one or the other or both.

Solution 3

To search for files containing all the words in any order anywhere:

grep -ril \'action\' | xargs grep -il \'model\' | xargs grep -il \'view_type\'

The first grep kicks off a recursive search (r), ignoring case (i) and listing (printing out) the name of the files that are matching (l) for one term ('action' with the single quotes) occurring anywhere in the file.

The subsequent greps search for the other terms, retaining case insensitivity and listing out the matching files.

The final list of files that you will get will the ones that contain these terms, in any order anywhere in the file.

Solution 4

If you have a grep with a -P option for a limited perl regex, you can use

grep -P '(?=.*string1)(?=.*string2)'

which has the advantage of working with overlapping strings. It's somewhat more straightforward using perl as grep, because you can specify the and logic more directly:

perl -ne 'print if /string1/ && /string2/'

Solution 5

Your method was almost good, only missing the -w

grep -w 'string1\|string2' filename
Share:
439,812

Related videos on Youtube

hearsaxas
Author by

hearsaxas

Updated on February 08, 2022

Comments

  • hearsaxas
    hearsaxas about 2 years

    I am trying to use grep to match lines that contain two different strings. I have tried the following but this matches lines that contain either string1 or string2 which not what I want.

    grep 'string1\|string2' filename
    

    So how do I match with grep only the lines that contain both strings?

    • AlikElzin-kilaka
      AlikElzin-kilaka over 6 years
    • Seamus
      Seamus about 2 years
      This question seems clear enough, yet most every answer here is wrong. I can't help but wonder why. It's easy enough to test: Create a file with 3 lines in it: 1. string1, 2. string2, 3. string1 string2. Now choose the accepted answer - or virtually any answer here - and you'll see that they do not give the correct answer. Hint: A correct answer is the one whose output is line 3., and only line 3..
    • jlhasson
      jlhasson about 2 years
      I think the title is ambiguous and could lead folks to think that matching either of the two strings could be correct. Not everyone reads the body of the question :)
  • Aquarius Power
    Aquarius Power over 10 years
    @AlexanderN indeed I cant make it work with multiline, thats so weird it was accepted..
  • Scott Prive
    Scott Prive over 9 years
    It was not a multiline question. If it were multiline, grep -P supports Perl style regex...
  • Scott Prive
    Scott Prive over 9 years
    Best answer. Shell is very easy and quick, but once the pattern gets complex you should use Python or Perl (or Awk). Don't beat your head against the wall trying to prove it can be done in pure shell (whatever that means these days). A reminder folks, these tools can be used in "one liner" syntax that are embed dibble into an existing shell script.
  • janosdivenyi
    janosdivenyi about 9 years
    wouldn't grep -e "string1" -e "string2" filename do the same?
  • s g
    s g almost 9 years
    @hearsaxas this should will regardless of the ordering since grep just searches the entire line and prints the entire line when there is a match
  • Leo
    Leo almost 9 years
    At least on OS-X and FreeBSD it does work! My guess is you're on something else (which the OP didn't define - hope you didn't downvote a correct answer to many users except you).
  • Ariel
    Ariel over 8 years
    I am on OS-X. Perhaps I am not doing this correctly? Take a look at what I did: i.imgur.com/PFVlVAG.png
  • Leo
    Leo over 8 years
    Odd. I expected the difference was in not grepping into file, but, if I pipe my method with your ls, I do get result that you don't: imgur.com/8eTt3Ak.png - Both on both OS-X 10.9.5 ("grep (BSD grep) 2.5.1-FreeBSD") and FreeBSD 10 ("grep (GNU grep) 2.5.1-FreeBSD"). I'm curious what's your grep -V is.
  • Ariel
    Ariel over 8 years
    Your examples are working for me: i.imgur.com/K8LM69O.png So the difference is that this method does not pick up substrings, they have to be complete strings on their own. I guess you will need to construct regexps within the grep to search for substrings. Something like this: grep -w 'regexp1\|regexp2' filename
  • lifeson106
    lifeson106 over 8 years
    Only works when both 'string1' AND 'string2' are on the same line. If you want to find lines with either 'string1' or 'string2', see user45949's answer.
  • orion elenzil
    orion elenzil over 8 years
    this is how to grep for string1 OR string2. the question clearly states they're looking for string1 AND string2.
  • masukomi
    masukomi over 8 years
    the first option: piping one grep into a second does NOT produce an OR result it produces an AND result.
  • r0estir0bbe
    r0estir0bbe about 8 years
    Pretty sure that the question is pretty precise: How do I match lines that contains *both* strings?
  • pitseeker
    pitseeker about 8 years
    As lifeson106 said this solution does not work if you want to match lines with either word1 or word2. The "grep -E" solution by user45949 works in that case.
  • Ravi Dhoriya ツ
    Ravi Dhoriya ツ about 8 years
    I used grep -e "string1" -e "string2"
  • gustafbstrom
    gustafbstrom over 7 years
    OP shows an example by matching string1 or string2 and asks how to match lines that contains both strings. This example still yields OR.
  • ife
    ife over 7 years
    Can it print with a same line?
  • luk2302
    luk2302 almost 7 years
    In what way is that different from at least the top two answers?
  • Tommy Harris
    Tommy Harris almost 7 years
    Agreed! I'll just note that I had to give xargs a "-d '\n'" to handle file names with spaces. This worked for me on Linux: grep -ril 'foo' | xargs -d '\n' grep -il 'bar'
  • Ben Wheeler
    Ben Wheeler almost 7 years
    This performs a logical AND. OP wants a logical OR.
  • Ben Wheeler
    Ben Wheeler almost 7 years
    Your statements are true, but don't answer OP question
  • Ugur
    Ugur over 6 years
    Works on a Mac, in iTerm. Excellent! Without backslashing the pipe!
  • Peter K
    Peter K over 5 years
    This does answer the question and this is indeed how most people write it.
  • Peter K
    Peter K over 5 years
    @Aquarius Power dot . doesn't match newline.
  • Erik I
    Erik I over 5 years
    @BenWheeler: From the question: "So how do I match with grep only the lines that contain both strings?"
  • BurntSushi5
    BurntSushi5 almost 5 years
    This answer isn't quite right. The named capturing groups are unnecessary, and this doesn't handle the case when string2 appears before string1. The simplest solution to this problem is rg string1 file.txt | rg string2.
  • Kamaraju Kusumanchi
    Kamaraju Kusumanchi almost 5 years
    Always thought that "git grep" can only be run inside a git repository. I Was not aware of the --no-index option. Thanks for pointing it out!
  • Admin
    Admin almost 5 years
    With GNU sed version 3.1, grep ‘string1\|string2’ FILENAME works
  • Hashim Aziz
    Hashim Aziz over 4 years
    Is awk '/R1/ && /R2/' case-insensitive?
  • Ed Morton
    Ed Morton over 4 years
    @Hashim - no. To make it case-insensitive with GNU awk you'd do awk -v IGNORECASE=1 '/R1/ && /R2/' and with any awk awk '{x=toupper($0)} x~/R1/ && x~/R2/'
  • Hashim Aziz
    Hashim Aziz over 4 years
    Why is this answer still here? It is NOT an answer to the question.
  • kap
    kap about 4 years
    The question clearly asks to find two strings (AND) and this answer is providing exactly that.
  • mchid
    mchid almost 4 years
    If you need color highlighting, you must use --color=always on both instead of --color=auto or it will only highlight one match and not the other.
  • mal
    mal almost 4 years
    It's still a useful answer to a closely related question that will bring people here. Like me for example, and apparently almost 200 others.
  • soMuchToLearnAndShare
    soMuchToLearnAndShare over 3 years
    the -e "string1" -e "string2" is good as it works for grep in a folder recursively nicely.
  • Seamus
    Seamus about 2 years
    :) Yes - you could try it, but it wouldn't work.
  • Seamus
    Seamus about 2 years
    Interesting answer, but this it does not answer the OP's question.
  • Seamus
    Seamus about 2 years
    No - the question is clear: the AND condition applies to the line ... not to the entire file. Your solution provides an OR condition for the line.
  • Seamus
    Seamus about 2 years
    No - the question is clear: the AND condition applies to the line: string1 AND string2 must appear on the same line ... Your solution provides string1 OR string2 for the line.
  • Seamus
    Seamus about 2 years
    You get the correct answer with your proposed solution, but you explained it oddly! In your command, the | is a pipe - it does not mean or; you do explain that later, but what is the reason for that first comment?
  • Seamus
    Seamus about 2 years
    This is not the only correct answer to the question, but it is the most elegant. It illustrates the principle of using the right tool for the job.
  • Seamus
    Seamus about 2 years
    This doesn't work because the first character after grep is not the single quote ' , but something that looks similar - hex value: e280980a (Unicode?) instead of 270a. Used echo "‘" | xxd -ps -c 20
  • Kinjal Dixit
    Kinjal Dixit about 2 years
    @Seamus the question has been edited since it was asked. The answer is related to the question but you have to understand that people come to questions that match something close to what they are looking for. while i don't answer the question, i do provide a related answer. going by the upvotes, the answer was helpful to others. please do not do your advocacy here and ruin the platform. this is the last 'social media' place where i am active. but i will not hesitate to quit if this place becomes woke.
  • Seamus
    Seamus about 2 years
    ??? please do not do your advocacy here and ruin the platform... No idea what you're on about, mate. It was an honest comment, and that is all. If you don't like it, that's fine, but you could have stopped after the first line. Me - "woke"?? ha ha ha
  • Leo
    Leo about 2 years
    Maybe mind that the question was edited, before going bold in bold.