RegEx:如何捕获子节

本文关键字:何捕获 RegEx | 更新日期: 2023-09-27 18:04:26

考虑以下简单的文本信息:

info
  start
    date=20140521
    val=key1
    info="Just a string"
  end
  start
    date=20140521
    val=key2
    info="Another one"
  end
end

我想使用RegEx捕获基于'val'字段值的部分。

为了方便示例,假设我想获得val=key1 section。

后面的正则表达式没有捕获任何东西!

(start((?=val=key1)(.|'s))*?end)

然而,如果我使用下面的一个,我可以捕获val=key2的部分(与我想要的相反)

(start((?!val=key1)(.|'s))*?end)

下面是本例中捕获的部分:

  start
    date=20140521
    val=key2
    info="Another one"
  end

有简单的方法吗?

RegEx:如何捕获子节

如果您想忽略除val=1以外的部分,您可以在这里使用以下命令。

(?s)(start((?!val='d+).)*val=1'b.*?end)

现场演示

:

  • 要回答更新的编辑,您可以使用以下命令捕获这些部分。

    (?s)(start((?!val='w+).)*val=key1'b.*?end)
    
    正则表达式:

    (?s)           set flags for this block (with . matching 'n)
    (              group and capture to '1:
     start         'start'
     (             group and capture to '2 (0 or more times)
     (?!           look ahead to see if there is not:
      val=         'val='
       'w+         word characters (a-z, A-Z, 0-9, _) (1 or more times)
     )             end of look-ahead
     .             any character
     )*            end of '2 
     val=key1      'val=key1'
       'b          the boundary between a word char ('w) and not a word char
     end           'end'
    )              end of '1
    

    现场演示

如果你只是想找到start's+val=1end之间的东西,你可以使用一些简单的东西,如:

(?s)'bstart's+val=1'b(.*?)'bend'b

您可以将val=1替换为您感兴趣的任何模式

您遇到的问题(示例输入没有捕捉到)是,在您想要的开始/结束块之前有一个开始/结束块,因为一个朴素的正则表达式,即使使用不情愿的量词,也会在目标值之前的第一个开始匹配。

解决方案是在匹配之前消耗尽可能多的输入:

.*(start.*?val=1'b.*?end)

查看实时演示,它在目标之前有一个额外的块,它被捕获为组1。

这个正则表达式必须与"dotall"标志一起使用,它将目标块捕获为第1组。"。*"在前面是一个很小但很重要的部分,它消耗你的目标前面的所有block。

如果需要的话,您可以通过在各个部分周围设置单词边界'b来更加严格。但是,建议在目标数字之后设置单词边界,这样像val=12这样的输入就不会意外匹配。