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

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

应该匹配。


当前回答

如果你需要两个单词彼此接近,例如不超过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命令。

其他回答

sed应该足够了,就像海报LJ上面说的,

而不是!d,你可以简单地使用p打印:

sed -n '/abc/,/efg/p' file

用银搜索器:

ag 'abc.*(\n|.)*efg' your_filename

与戒指持有者的答案相似,但用ag代替。银色搜索者的速度优势可能在这里大放异彩。

如果可以使用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

我在几天前发布了一个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上找到更多信息。

如果你需要两个单词彼此接近,例如不超过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命令。