简体   繁体   中英

Search two patterns on two consecutive lines and print n lines before the match

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM