下一行不包含字符串的 grep 字符串

tim*_*tim 5 command-line grep search text-processing

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

例如,这个:

foo1 searchString bar
foo1 excludeString bar

foo2 searchString bar
something else

foo3 searchString bar

foo3 excludeString bar

foo4 searchString bar
Run Code Online (Sandbox Code Playgroud)

应该返回这个:

foo2 searchString bar
foo3 searchString bar
foo4 searchString bar
Run Code Online (Sandbox Code Playgroud)

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

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

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

jim*_*mij 8

您可以使用pERL compatible regular eXpressions的grep

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

它搜索searchString后跟任何字符.,重复零次或多次*\n 当旁边没有( ?!) 模式时才搜索新行.*excludeString-M存在选项以匹配多行。


don*_*sti 6

sed

sed '/searchString/!d;$!N;/\n.*excludeString/!P;D' infile
Run Code Online (Sandbox Code Playgroud)

这个怎么运作:

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

  • 我花了十分钟的时间来理解手册页,我想我们的许多用户都觉得这比我做的更难——毕竟,我们有成员说他们在阅读手册页时遇到了困难(谁能责怪?他们?)。如您所知,我们正在寻找能够提供一些解释和背景的详细答案。我有正确的单行答案,这些答案不那么神秘,因为缺乏解释而被否决。你愿意剖析你的答案,说出每个部分的作用吗?(例如,我需要几分钟才能弄清楚为什么你的最后一个命令是 `D` 而不是 `d`。) (2认同)