我想找到有“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..
应该匹配。
当前回答
文件模式*.sh对于防止目录被检查很重要。当然,一些测试也可以防止这种情况发生。
for f in *.sh
do
a=$( grep -n -m1 abc $f )
test -n "${a}" && z=$( grep -n efg $f | tail -n 1) || continue
(( ((${z/:*/}-${a/:*/})) > 0 )) && echo $f
done
The
grep -n -m1 abc $f
搜索最大1个匹配项并返回(-n)行数。 如果找到一个匹配(test -n…),找到efg的最后一个匹配(找到所有,并使用tail -n 1取最后一个匹配)。
z=$( grep -n efg $f | tail -n 1)
其他的继续。
由于结果类似于18:foofile.sh String alf="abc";我们需要从“:”开始切到行尾。
((${z/:*/}-${a/:*/}))
如果第二个表达式的最后一个匹配超过了第一个表达式的第一个匹配,则应返回正结果。
然后我们报告文件名echo $f。
其他回答
我在几天前发布了一个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上找到更多信息。
你至少有几个选择
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!!
如果您对模式序列不感兴趣,可以使用grep。
grep -l "pattern1" filepattern*.* | xargs grep "pattern2"
例子
grep -l "vector" *.cpp | xargs grep "map"
Grep -l将找到与第一个模式匹配的所有文件,xargs将为第二个模式查找Grep。希望这能有所帮助。
遗憾的是,你不能。来自grep文档:
grep搜索指定的输入FILEs(或标准输入,如果没有指定文件,或如果给出了一个连字符减号(-)作为文件名),以查找包含与给定PATTERN匹配的行。
如果您愿意使用上下文,这可以通过输入来实现
grep -A 500 abc test.txt | grep -B 500 efg
这将显示“abc”和“efg”之间的所有内容,只要它们之间的距离不超过500行。