我想找到有“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..
应该匹配。
当前回答
#!/bin/bash
shopt -s nullglob
for file in *
do
r=$(awk '/abc/{f=1}/efg/{g=1;exit}END{print g&&f ?1:0}' file)
if [ "$r" -eq 1 ];then
echo "Found pattern in $file"
else
echo "not found"
fi
done
其他回答
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
虽然sed选项是最简单、最简单的,但遗憾的是,LJ的一行程序并不是最可移植的。那些受困于C Shell(而不是bash)版本的人将需要摆脱他们的刘海:
sed -e '/abc/,/efg/\!d' [file]
不幸的是,这一行在bash等中不起作用。
我不知道如何用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。
sed应该足够了,就像海报LJ上面说的,
而不是!d,你可以简单地使用p打印:
sed -n '/abc/,/efg/p' file
使用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