我想找到有“abc”和“efg”的文件,这两个字符串在该文件中的不同行。一个包含以下内容的文件:

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

应该匹配。


当前回答

我在几天前发布了一个grep替代方案,它直接支持这一点,通过多行匹配或使用条件——希望它对搜索这里的人有用。下面是示例命令的样子:

多行:

sift -lm 'abc.*efg' testfile

条件:

sift -l 'abc' testfile --followed-by 'efg'

你也可以指定'efg'必须在一定的行数内跟在'abc'后面:

sift -l 'abc' testfile --followed-within 5:'efg'

你可以在sift-tool.org上找到更多信息。

其他回答

如果您对模式序列不感兴趣,可以使用grep。

grep -l "pattern1" filepattern*.* | xargs grep "pattern2"

例子

grep -l "vector" *.cpp | xargs grep "map"

Grep -l将找到与第一个模式匹配的所有文件,xargs将为第二个模式查找Grep。希望这能有所帮助。

我用它从一个multi fasta文件中提取一个fasta序列,使用grep的-P选项:

grep -Pzo ">tig00000034[^>]+"  file.fasta > desired_sequence.fasta

基于perl的搜索 Z表示行以0字节结尾,而不是换行字符 O来捕获匹配的内容,因为grep返回整行(在本例中,因为您做了-z是整个文件)。

regexp的核心是[^>],它翻译为“不大于符号”。

使用ripgrep可以:

$ rg --multiline 'abc(\n|.)+?efg' test.txt
3:blah abc blah
4:blah abc blah
5:blah blah..
6:blah blah..
7:blah blah..
8:blah efg blah blah

或者其他咒语。

如果你愿意的话。作为换行符计算:

$ rg --multiline '(?s)abc.+?efg' test.txt
3:blah abc blah
4:blah abc blah
5:blah blah..
6:blah blah..
7:blah blah..
8:blah efg blah blah

或者等效于(?s)的是rg -multiline- multiline-dotall

为了回答最初的问题,它们必须在不同的行上:

$ rg——multiline 'abc.*[\n](\n|.)*efg' test.txt

如果你想让它“非贪婪”,这样你就不会用最后一个efg得到第一个abc(把它们分成成对):

$ rg——multiline 'abc.*[\n](\n|.)*?efg的用法

https://til.hashrocket.com/posts/9zneks2cbv-multiline-matches-with-ripgrep-rg

这可以通过首先使用tr用其他字符替换换行符来轻松完成:

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

这里,我使用警报字符\a (ASCII 7)来代替换行符。 这在你的文本中几乎找不到,而且grep可以用一个.匹配它,或者专门用\a匹配它。

Grep是这种操作的笨拙工具。

在大多数现代Linux系统中都可以找到pcregrep,可以用作

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

where -M,——multiline允许模式匹配多行

还有一个更新的pcre2grep。两者都是由PCRE项目提供的。

pcre2grep可以通过Mac Ports作为pcre2端口的一部分用于Mac OS X:

% sudo port install pcre2 

并通过Homebrew为:

% brew install pcre

或者pcre2

% brew install pcre2

pcre2grep在Linux (Ubuntu 18.04+)上也可用

$ sudo apt install pcre2-utils # PCRE2
$ sudo apt install pcregrep    # Older PCRE