我想找到有“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..
应该匹配。
当前回答
作为Balu Mohan的答案的替代方案,可以只使用grep、head和tail来强制模式的顺序:
for f in FILEGLOB; do tail $f -n +$(grep -n "pattern1" $f | head -n1 | cut -d : -f 1) 2>/dev/null | grep "pattern2" &>/dev/null && echo $f; done
不过,这个不太漂亮。格式化得更容易读:
for f in FILEGLOB; do
tail $f -n +$(grep -n "pattern1" $f | head -n1 | cut -d : -f 1) 2>/dev/null \
| grep -q "pattern2" \
&& echo $f
done
这将打印所有“pattern2”出现在“pattern1”之后,或者两者都出现在同一行的文件名称:
$ echo "abc
def" > a.txt
$ echo "def
abc" > b.txt
$ echo "abcdef" > c.txt; echo "defabc" > d.txt
$ for f in *.txt; do tail $f -n +$(grep -n "abc" $f | head -n1 | cut -d : -f 1) 2>/dev/null | grep -q "def" && echo $f; done
a.txt
c.txt
d.txt
解释
Tail -n +i -打印第i行之后的所有行,包括 Grep -n -在匹配的行前加上行号 头-n1 -只打印第一行 Cut -d: -f 1 -打印第一个切割列,使用:作为分隔符 2>/dev/null -如果$()表达式返回空,则出现沉默尾部错误输出 Grep -q—关闭Grep并在找到匹配时立即返回,因为我们只对退出码感兴趣
其他回答
在所有文件中递归搜索(在每个文件中的多行中),同时存在两个字符串(即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' *
遗憾的是,你不能。来自grep文档:
grep搜索指定的输入FILEs(或标准输入,如果没有指定文件,或如果给出了一个连字符减号(-)作为文件名),以查找包含与给定PATTERN匹配的行。
sed应该足够了,就像海报LJ上面说的,
而不是!d,你可以简单地使用p打印:
sed -n '/abc/,/efg/p' file
我不确定是否可以使用grep,但sed使它非常简单:
sed -e '/abc/,/efg/!d' [file-with-content]
你至少有几个选择
DOTALL方法
用(?s) DOTALL the。包含\n的字符 你也可以使用一个超前(?=\n)——不会在匹配中被捕获
example-text:
true
match me
false
match me one
false
match me two
true
match me three
third line!!
{BLANK_LINE}
命令:
grep -Pozi '(?s)true.+?\n(?=\n)' example-text
-p用于perl正则表达式
-o只匹配模式,而不是整行
-z允许换行
-i不区分大小写
输出:
true
match me
true
match me three
third line!!
注:
- +? makes modifier non-greedy so matches shortest string instead of largest (prevents from returning one match containing entire text)
你可以使用老式的O.G.手动方法,使用\n
命令:
grep -Pozi 'true(.|\n)+?\n(?=\n)'
输出:
true
match me
true
match me three
third line!!