grep 字符串,其中下一行不包含字符串

grep 字符串,其中下一行不包含字符串

我想在目录及其子目录内的所有文件中搜索包含特定字符串的行,但我想排除那些紧随其后的行中包含不同特定字符串的结果。

例如,这个:

foo1 searchString bar
foo1 excludeString bar

foo2 searchString bar
something else

foo3 searchString bar

foo3 excludeString bar

foo4 searchString bar

应该返回这个:

foo2 searchString bar
foo3 searchString bar
foo4 searchString bar

我知道-A打印多行,并且-v排除结果。但我目前的做法grep -r -A 1 "searchString" | grep -v "excludeString"显然行不通。

有没有办法告诉第二个 grep 如果找到匹配项,它也应该删除前一行?或者我可以通过其他方式实现这一目标?

性能并不是我最关心的问题;如果该命令相对容易记住,那就太好了。

答案1

您可以使用perlc兼容的r常规e表达式grep

$ pcregrep -M '(searchString.*\n)(?!.*excludeString)' file
foo2 searchString bar
foo3 searchString bar
foo4 searchString bar

它搜索searchString后跟任何字符.,重复零次或多次*,后跟新行\n 仅有的如果有不是旁边的( ?!) 图案。存在.*excludeString选项-M是为了匹配多行。

答案2

sed

sed '/searchString/!d;$!N;/\n.*excludeString/!P;D' infile

怎么运行的:

  • /searchString/!d如果不匹配则删除该行searchString并读入新行,重新开始命令循环(即不再执行其余命令)
  • 如果该行匹配searchStringsed则执行$!N;/\n.*excludeString/!P;D- 请参阅这里怎么运行的;不同之处在于,这里,它在 ewline 字符excludeString之后查找模式,\n以便匹配两者的行,searchString并且excludeString如果后面没有匹配的行,仍然会打印excludeString;如果没有与searchStringexcludeString(即已知输入)相匹配的行,那么您可以删除该\n.*部分并运行:
    sed '/searchString/!d;$!N;/excludeString/!P;D' infile

相关内容