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

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

应该匹配。


当前回答

如果你对你要找的两个字符串'abc'和'efg'之间的距离有一些估计,你可以使用:

grep -r . -e 'abc' -A num1 -B num2 | grep 'efg'

这样,第一个grep将返回'abc' + #num1行,后面是#num2行,第二个grep将筛选所有这些以获得'efg'。 然后您将知道它们同时出现在哪些文件中。

其他回答

下面是一个受到这个答案启发的解决方案:

如果'abc'和'efg'可以在同一行: Grep -zl 'abc。*efg' <您的文件列表> 如果'abc'和'efg'必须在不同的行上: grep -Pzl '(?s)abc.*\n.;*efg' <您的文件列表>

参数:

-P使用perl兼容的正则表达式。 将输入视为一组行,每一行以0字节结束,而不是换行符。例如,grep将输入视为一行。注意,如果你不使用-l,它将显示匹配后的NUL字符,见注释。 -l list只匹配文件名。 (?s)激活PCRE_DOTALL,这意味着'。'查找任何字符或换行符。

随着几个月前ugrep的发布:

ugrep 'abc(\n|.)+?efg'

这个工具是高度优化的速度。它也是GNU/BSD/PCRE-grep兼容的。

注意我们应该使用惰性重复+?,除非您想将所有efg行匹配在一起,直到文件中的最后一个efg。

如果可以使用Perl,就可以很容易地做到这一点。

perl -ne 'if (/abc/) { $abc = 1; next }; print "Found in $ARGV\n" if ($abc && /efg/); }' yourfilename.txt

您也可以使用单个正则表达式来实现这一点,但这涉及到将文件的整个内容放入单个字符串中,对于大型文件,这可能会占用太多内存。 为了完整起见,下面是该方法:

perl -e '@lines = <>; $content = join("", @lines); print "Found in $ARGV\n" if ($content =~ /abc.*efg/s);' yourfilename.txt

在所有文件中递归搜索(在每个文件中的多行中),同时存在两个字符串(即string1和string2在不同的行中,并且都存在于同一个文件中):

grep -r -l 'string1' * > tmp; while read p; do grep -l 'string2' $p; done < tmp; rm tmp 

在所有文件中递归搜索(在每个文件中的多行中),使用EITHER字符串存在(即string1和string2在不同的行中,并且在同一个文件中存在):

grep -r -l 'string1\|string2' * 

如果你需要两个单词彼此接近,例如不超过3行,你可以这样做:

find . -exec grep -Hn -C 3 "abc" {} \; | grep -C 3 "efg"

同样的例子,但是只过滤*.txt文件:

find . -name *.txt -exec grep -Hn -C 3 "abc" {} \; | grep -C 3 "efg"

如果你想,你也可以用正则表达式替换grep命令。