I want to grep or search using shell commands for two consecutive lines that match two different patterns, eg match for line1: "abc", for line2: "def". So, for the following text there should be one match: lines 4 and 5.
1234
abc-noise
6789
abc-noise
def-noise
def-noise
1234
When I find such a match I want to print it including N lines before the match. Any ideas? Thanks.
Use GNU grep
in PCRE
mode, with -P
flag enabled,
grep -ozP ".*abc.*\n.*def.*" file
Using pcregrep
for an input file
cat file
1234
abc-noise
6789
abc-noise
def-noise
def-noise
1234
noise-abc-noise
noise-noise-def
For multi-line pattern-match, do
pcregrep -M 'abc.*\n.*def' file
abc-noise
def-noise
noise-abc-noise
noise-noise-def
And for lines before the pattern match, use the -B
flag as in GNU grep
pcregrep -B2 -M 'abc.*\n.*def' file
abc-noise
6789
abc-noise
def-noise
def-noise
1234
noise-abc-noise
noise-noise-def
More about the flags -M
and -B
from the man pcregrep
page,
-M, --multiline Allow patterns to match more than one line. When this option is given, patterns may usefully contain literal newline characters and internal occurrences of ^ and $ characters. The output for a successful match may consist of more than one line, the last of which is the one in which the match ended. If the matched string ends with a newline sequence the output ends at the end of that line.
-B number, --before-context=number Output number lines of context before each matching line. If filenames and/or line numbers are being output, a hyphen separator is used instead of a colon for the context lines. A line containing "--" is output between each group of lines, unless they are in fact contiguous in the input file.
Expanding on @Inian's great answer, if you want to do search recursively through a whole directory:
find my_code_dir/ -type f -name "*.py" -exec pcregrep -B2 -M 'except.*\n.*pass' {} +
This particular command will find occurrences lines containing except
followed immediately by a line containing pass
, but only in .py
files.
#!/bin/bash
a=''
b=''
while read c; do
a=$b;
b=$c;
if [ `echo "$a" |grep "abc"` ] & [ `echo "$b" |grep "def"` ]; then
echo $a;
echo $b;
break;
fi
done
Launch:
$./find2pat
wegweg
egwergwerg
sdfabcerg
rrheedef4
Output:
sdfabcerg
rrheedef4
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.