How to find patterns across multiple lines using g

2018-12-31 09:42发布

I want to find files that have "abc" AND "efg" in that order, and those two strings are on different lines in that file. Eg: a file with content:

blah blah..
blah blah..
blah abc blah
blah blah..
blah blah..
blah blah..
blah efg blah blah
blah blah..
blah blah..

Should be matched.

标签: regex grep
21条回答
只若初见
2楼-- · 2018-12-31 10:14

If you are willing to use contexts, this could be achieved by typing

grep -A 500 abc test.txt | grep -B 500 efg

This will display everything between "abc" and "efg", as long as they are within 500 lines of each other.

查看更多
琉璃瓶的回忆
3楼-- · 2018-12-31 10:18

awk one-liner:

awk '/abc/,/efg/' [file-with-content]
查看更多
初与友歌
4楼-- · 2018-12-31 10:18

This should work:

cat FILE | egrep 'abc|efg'

If there is more than one match you can filter out using grep -v

查看更多
爱死公子算了
5楼-- · 2018-12-31 10:19

Grep is not sufficient for this operation.

pcregrep which is found in most of the modern Linux systems can be used as

pcregrep -M  'abc.*(\n|.)*efg' test.txt

There is a newer pcre2grep also. Both are provided by the PCRE project.

pcre2grep is available for Mac OS X via Mac Ports as part of port pcre2:

% sudo port install pcre2 

and via Homebrew as:

% brew install pcre

or for pcre2

% brew install pcre2
查看更多
无色无味的生活
6楼-- · 2018-12-31 10:22

I released a grep alternative a few days ago that does support this directly, either via multiline matching or using conditions - hopefully it is useful for some people searching here. This is what the commands for the example would look like:

Multiline: sift -lm 'abc.*efg' testfile
Conditions: sift -l 'abc' testfile --followed-by 'efg'

You could also specify that 'efg' has to follow 'abc' within a certain number of lines:
sift -l 'abc' testfile --followed-within 5:'efg'

You can find more information on sift-tool.org.

查看更多
公子世无双
7楼-- · 2018-12-31 10:23

This can be done easily by first using tr to replace the newlines with some other character:

tr '\n' '\a' | grep 'abc.*def' | tr '\a' '\n'

Here, I am using the alarm character, \a (ASCII 7) in place of a newline. This is almost never found in your text, and grep can match it with a ., or match it specifically with \a.

查看更多
登录 后发表回答