Match two strings in one line with grep
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
Related videos on Youtube
hearsaxas
Updated on February 08, 2022Comments
-
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 over 6 years
-
Seamus about 2 yearsThis 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 about 2 yearsI 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 over 10 years@AlexanderN indeed I cant make it work with multiline, thats so weird it was accepted..
-
Scott Prive over 9 yearsIt was not a multiline question. If it were multiline, grep -P supports Perl style regex...
-
Scott Prive over 9 yearsBest 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 about 9 yearswouldn't
grep -e "string1" -e "string2" filename
do the same? -
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 almost 9 yearsAt 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 over 8 yearsI am on OS-X. Perhaps I am not doing this correctly? Take a look at what I did: i.imgur.com/PFVlVAG.png
-
Leo over 8 yearsOdd. 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 over 8 yearsYour 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 over 8 yearsOnly 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 over 8 yearsthis is how to grep for string1 OR string2. the question clearly states they're looking for string1 AND string2.
-
masukomi over 8 yearsthe first option: piping one grep into a second does NOT produce an OR result it produces an AND result.
-
r0estir0bbe about 8 yearsPretty sure that the question is pretty precise:
How do I match lines that contains *both* strings?
-
pitseeker about 8 yearsAs 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 ツ about 8 yearsI used
grep -e "string1" -e "string2"
-
gustafbstrom over 7 yearsOP shows an example by matching string1 or string2 and asks how to match lines that contains both strings. This example still yields OR.
-
ife over 7 yearsCan it print with a same line?
-
luk2302 almost 7 yearsIn what way is that different from at least the top two answers?
-
Tommy Harris almost 7 yearsAgreed! 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 almost 7 yearsThis performs a logical AND. OP wants a logical OR.
-
Ben Wheeler almost 7 yearsYour statements are true, but don't answer OP question
-
Ugur over 6 yearsWorks on a Mac, in iTerm. Excellent! Without backslashing the pipe!
-
Peter K over 5 yearsThis does answer the question and this is indeed how most people write it.
-
Peter K over 5 years@Aquarius Power dot
.
doesn't match newline. -
Erik I over 5 years@BenWheeler: From the question: "So how do I match with grep only the lines that contain both strings?"
-
BurntSushi5 almost 5 yearsThis answer isn't quite right. The named capturing groups are unnecessary, and this doesn't handle the case when
string2
appears beforestring1
. The simplest solution to this problem isrg string1 file.txt | rg string2
. -
Kamaraju Kusumanchi almost 5 yearsAlways 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 almost 5 yearsWith GNU sed version 3.1, grep ‘string1\|string2’ FILENAME works
-
Hashim Aziz over 4 yearsIs
awk '/R1/ && /R2/'
case-insensitive? -
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 awkawk '{x=toupper($0)} x~/R1/ && x~/R2/'
-
Hashim Aziz over 4 yearsWhy is this answer still here? It is NOT an answer to the question.
-
kap about 4 yearsThe question clearly asks to find two strings (AND) and this answer is providing exactly that.
-
mchid almost 4 yearsIf 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 almost 4 yearsIt'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 over 3 yearsthe -e "string1" -e "string2" is good as it works for grep in a folder recursively nicely.
-
Seamus about 2 years:) Yes - you could try it, but it wouldn't work.
-
Seamus about 2 yearsInteresting answer, but this it does not answer the OP's question.
-
Seamus about 2 yearsNo - 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 about 2 yearsNo - the question is clear: the AND condition applies to the line:
string1
ANDstring2
must appear on the same line ... Your solution providesstring1
ORstring2
for the line. -
Seamus about 2 yearsYou get the correct answer with your proposed solution, but you explained it oddly! In your command, the
|
is apipe
- it does not mean or; you do explain that later, but what is the reason for that first comment? -
Seamus about 2 yearsThis 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 about 2 yearsThis doesn't work because the first character after
grep
is‘
not the single quote'
, but something that looks similar - hex value:e280980a
(Unicode?) instead of270a
. Usedecho "‘" | xxd -ps -c 20
-
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 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 about 2 yearsMaybe mind that the question was edited, before going bold in bold.