How can I search for two different phrases when they are on two different lines by using a single grep
command?
For example
Line 1: This is a sweet.
Line 2: lemon.
I used this but no result
grep "sweet.*lemon" file_type
How can I search for two different phrases when they are on two different lines by using a single grep
command?
For example
Line 1: This is a sweet.
Line 2: lemon.
I used this but no result
grep "sweet.*lemon" file_type
To use grep
for two different lines, search for both patterns
$ grep -e sweet -e lemon file_type
This is a sweet
lemon.
Or use alternation
$ grep -E 'sweet|lemon' file_type
This is a sweet
lemon.
To get the next line after a pattern, you could use the context option
$ grep -A1 sweet file_type
This is a sweet
lemon.
But if you're searching explicitly for a multiline pattern, that's tricky because grep
thinks in lines.... Your .*
will catch everything between "sweet" and "lemon" on the line. We can get "lemon" on the next line with -P
using \n
to match the newline and by telling grep
the file is null separated with -z
:
$ grep -zPo 'This is a sweet\nlemon' file_type
This is a sweet
lemon.
-E
Use extended regular expressions (to use |
character for alternation without needing to escape it)-An
Print additional lines after the pattern, where n is the number of trailing lines to print-P
Use perl-style regular expressions ("experimental" in grep
- install pcregrep
instead for better perl regex support)-z
Use the null character as separator (just pretending in this case, but grep
will take our word for it)-o
only print the matched partLike this:
grep "sweet\|lemon"
grep
by default works in "standard mode", where "special characters" like |
, +
, *
are interpreted literally unless they're masked with a backslash. See for example this answer. To use the way you're probably used to, that "special characters" need to be masked to be interpreted literally, you need to switch to "extended mode" (grep -E
). Maybe madneon could elaborate a bit more on his answers, for example what the OPs try would have matched?
– Henning Kockerbeck
Dec 10 '16 at 10:51
Here is a pretty robust method for teasing out two lines which appear adjacent. I've laid it out so that the line order does not matter, but if it does matter this can be easily adjusted.
First I created a file with lines:
dog
fish
elephant
wombat
cat
pickle
anglepoise lamp
Then I performed the following tests to demonstrate a use of grep including -A and -B to tease out just the two lines in question.
2020-08-14 02:08:45 → touch Desktop/test/file.txt
2020-08-14 10:01:03 → grep -A1 -B1 cat Desktop/test/file.txt
wombat
cat
pickle
2020-08-14 10:01:10 → grep -A1 -B1 cat Desktop/test/file.txt | grep -A1 -B1 wombat
wombat
cat
2020-08-14 10:01:27 → grep -A1 -B1 cat Desktop/test/file.txt | grep -A1 -B1 pickle
cat
pickle
2020-08-14 10:01:49 →
What's going on? First A and B mean after and before. So we are grepping for our term (cat) and including in the response one line after and one line before our target line. This will yield two or three lines depending if the target line is a first or last line (2 lines) or if the target line is somewhere else in the file. (A file with a single line can only return one line, obviously.)
Then we grep those results using the same method with the second search term. This will cut the three lines from above to two lines unless both terms happen to appear on the same line.
grep: The -P and -z options cannot be combined
- e.g. grep (GNU grep) 2.5.1 on RHEL – Jason Pyeron Sep 23 '18 at 11:22lemon
isn't there, it still returns0
(non-error). – Joshua Pinter Aug 10 '20 at 21:20grep -zPo 'This is a sweet\nlemon' file
returns 1 if lemon is not there.grep -E 'sweet|lemon' file
returns 0 if sweet OR lemon is there. What result are you looking for? (You may want to ask a new question) – Zanna Aug 11 '20 at 07:49grep -E 'sweet|lemon' file
and that returned0
when either one was there. Didn't realize that thegrep -zPo
method acted more like an AND. Thanks for clarifying! – Joshua Pinter Aug 11 '20 at 15:47