使用 pcregrep grep 多行

Using pcregrep to grep multiple lines

我有一个具有以下模式的文件。

Foo $var1
.........
.........

Foo $var2 
..........
..........
..........
Yes

我只想匹配以 "Foo" 开头并具有 "Yes" 的 "section"。 (您会注意到每个部分末尾都有一个空换行符)

预期的输出应该是。

Foo $var2 
..........
..........
..........
Yes

我试过了

pcregrep -M "^Foo(.|\n)*^Yes"

但不幸的是,这从上一节开始匹配,并将倒数第二节与具有 "Yes" 的节合并为返回匹配项,因此我没有得到以 [= 开头的节28=] 并且有 "Yes" 但以 "Foo"

开头的部分与之前一样多

我的困境是如果在本节末尾我看不到 "Yes" 尽管我匹配了 "Foo".

如何丢弃之前的匹配

我尝试使用 lookbehind 函数,但它不能用于可变长度。

如果您使用启用了 PCRE 的 grep,将得到这样的结果
只是那些 Foo 带有 YES

请注意,我不确定 grep 是否会跨行。
可能,但我个人不知道。

(?m)^Foo\K(?:(?!^Foo)[\S\s])+(?=^Yes)

https://regex101.com/r/HCrcGO/1

展开

 (?m)
 ^ Foo
 \K 
 (?:
      (?! ^ Foo )
      [\S\s] 
 )+
 (?= ^ Yes )

如果可以改用 gnu awk,则可以使 awk 像这样在块模式下工作:

awk -v RS='Foo' -v ORS='' '/Yes/ {print RS[=10=]}' file
Foo $var2
..........
..........
..........
Yes

您可以从字符串的开头使用匹配 Foo,然后匹配所有不以 Yes 或 Foo 开头的行。

如果 Foo 和 Yes 不应该是更大单词的一部分,您可以使用单词边界 \b

^Foo\b.*(?:\n(?!Yes\b|Foo\b).*)*\nYes\b

部分

  • ^ 字符串开头
  • Foo\b.* 匹配 Foo 后跟除换行符之外的任何字符 0+ 次
  • (?:非捕获组
    • \n 匹配换行符
    • (?!Yes\b|Foo\b)否定前瞻,直接在右边断言not Yes或Foo
    • .* 匹配除换行符之外的任何字符 0+ 次
  • )*关闭组重复0+次
  • \nYes\b

Regex demo

例如

pcregrep -Mo '^Foo\b.*(?:\n(?!Yes\b|Foo\b).*)*\nYes\b' file

输出

Foo $var2
..........
..........
..........
Yes