Regex 使用pcregrep对多行进行grep

Regex 使用pcregrep对多行进行grep,regex,grep,pcregrep,Regex,Grep,Pcregrep,我有一个具有以下模式的文件 Foo $var1 ......... ......... Foo $var2 .......... .......... .......... Yes 我只想匹配以“Foo”开头并有“Yes”的“section”。(您会注意到在每个部分的末尾都有一个空行提要) 预期输出应为 Foo $var2 .......... .......... .......... Yes 我试过了 pcregrep-M“^Foo(.\n)*^Yes” 但不幸的是,这将从上一节开

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

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

Foo $var2 
..........
..........
..........
Yes
我只想匹配以“Foo”开头并有“Yes”的“section”。(您会注意到在每个部分的末尾都有一个空行提要)

预期输出应为

Foo $var2 
..........
..........
..........
Yes
我试过了

pcregrep-M“^Foo(.\n)*^Yes”

但不幸的是,这将从上一节开始匹配,并将倒数第二节和返回匹配的“是”部分合并在一起,所以我并没有得到一个以“Foo”开头并有“Yes”的部分,而是得到了和之前以“Foo”开头的部分一样多的部分

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


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

如果您使用的是启用PCRE的grep,类似的功能将得到
只有那些带有“是”的“Foo”

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

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

扩大

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

如果您可以使用
gnu awk
,则可以使
awk
在块模式下工作,如下所示:

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

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

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

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

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

比如说

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

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

请将该示例输入的所需输出(无描述)添加到您的问题中(无评论)。我如何使该模式适应pcregrep?@henrychiedozie-我不确定,除了它在PCRE下工作之外。也许试一下?它不起作用。它显示了这个错误。pcregrep:命令行正则表达式中偏移量11处出错:在(?或)之后无法识别字符(?-但我想让它起作用的方法是将积极的前瞻和消极的前瞻结合起来。但让它起作用的模式是我仍在试图弄清楚的。@dochenaj-这里是关于整个PCREGREP事情的一些信息,祝你愉快!选项设置-
(?m)设置多行匹配。PCRE_无大小写、PCRE_多行、PCRE_DOTALL和PCRE_扩展选项(与Perl兼容)的设置可以在模式内通过一系列包含在“(?”和“)之间的Perl选项字母进行更改
MATCH POINT RESET-
\K RESET start of MATCH
这很有效。但我必须充实单词边界。最后将其缩减为,pcregremp-Mo'^Foo.*(:\n(?!Foo.*)*\nYes'。