1

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

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

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

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

预期的输出应该是。

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

我试过了

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

但不幸的是,这从前一部分开始匹配,并将倒数第二部分与具有“是”作为返回匹配的部分混为一谈,所以我没有得到一个以“Foo”开头并具有“是”的部分,但是与以前一样多的以“Foo”开头的部分

我的困境是,如果在本节末尾我看不到“是”,但我匹配了“Foo”,如何丢弃上一个匹配项。

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

4

3 回答 3

1

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

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

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

在零件

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

正则表达式演示

例如

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

输出

Foo $var2
..........
..........
..........
Yes
于 2019-09-14T10:22:27.133 回答
0

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

awk -v RS='Foo' -v ORS='' '/Yes/ {print RS$0}' file
Foo $var2
..........
..........
..........
Yes
于 2019-09-14T07:02:41.953 回答
-1

如果您使用的是启用 PCRE 的 grep,这样的事情只会得到
那些FooYES

请注意,我不确定 grep 是否会跨越行。
应该是吧,但我个人不知道。

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

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

展开

 (?m)
 ^ Foo
 \K 
 (?:
      (?! ^ Foo )
      [\S\s] 
 )+
 (?= ^ Yes )
于 2019-09-13T20:49:47.403 回答