我想找到有“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”的文件,这两个字符串在该文件中的不同行。一个包含以下内容的文件:
blah blah..
blah blah..
blah abc blah
blah blah..
blah blah..
blah blah..
blah efg blah blah
blah blah..
blah blah..
应该匹配。
当前回答
如果可以使用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
其他回答
sed应该足够了,就像海报LJ上面说的,
而不是!d,你可以简单地使用p打印:
sed -n '/abc/,/efg/p' file
如果你对你要找的两个字符串'abc'和'efg'之间的距离有一些估计,你可以使用:
grep -r . -e 'abc' -A num1 -B num2 | grep 'efg'
这样,第一个grep将返回'abc' + #num1行,后面是#num2行,第二个grep将筛选所有这些以获得'efg'。 然后您将知道它们同时出现在哪些文件中。
虽然sed选项是最简单、最简单的,但遗憾的是,LJ的一行程序并不是最可移植的。那些受困于C Shell(而不是bash)版本的人将需要摆脱他们的刘海:
sed -e '/abc/,/efg/\!d' [file]
不幸的是,这一行在bash等中不起作用。
这可以通过首先使用tr用其他字符替换换行符来轻松完成:
tr '\n' '\a' | grep -o 'abc.*def' | tr '\a' '\n'
这里,我使用警报字符\a (ASCII 7)来代替换行符。 这在你的文本中几乎找不到,而且grep可以用一个.匹配它,或者专门用\a匹配它。
我不知道如何用grep做到这一点,但我会用awk做这样的事情:
awk '/abc/{ln1=NR} /efg/{ln2=NR} END{if(ln1 && ln2 && ln1 < ln2){print "found"}else{print "not found"}}' foo
不过,你需要注意如何做到这一点。您希望正则表达式匹配子字符串还是整个单词?适当添加\w标记。此外,虽然这严格符合您陈述的示例,但当abc在efg之后第二次出现时,它并不完全有效。如果你想处理这个问题,在/abc/ case等中添加一个If。