Regex lookback(?).最多只能在标识符后面和后面的第一个标签

本文关键字:标识符 标签 第一个 lookback Regex | 更新日期: 2023-09-27 18:13:05

我有一个字符串包含一个简单的xml结构:

<folder>
 <id=1>
 <id=6>
 <folder>
  <id=2>
  <id=6>
 </folder>
 <folder>
  <id=3>
  <id=5>
 </folder>
</folder>

我如何使用regex瞄准包含id=x的文件夹?

例如,如果id=2,我只想返回<folder><id=2><id=6></folder>

Regex lookback(?).最多只能在标识符后面和后面的第一个标签

下面应该可以工作:

<folder>'s*(<id='d+>)*'s*<id=xxx>.*?</folder>

注意你的字符串包含换行字符:你应该不能使用"DOTALL"选项。如何启用此选项取决于您使用的语言。

在c#的情况下,似乎你需要启用单行模式:

Regex.Matches(input, pattern, RegexOptions.Singleline)

使用grep和id=2的例子:

$ grep -Pzo '(?s)<folder>'s*(<id='d+>)*'s*<id=2>.*?</folder>' a
<folder>
  <id=2>
  <id=6>
 </folder>

(此处(?s)启用DOTALL)

解决方案

<folder>(?:(?!</?folder>).)*<id=2>(?:(?!</?folder>).|(?<open><folder>)|(?<-open></folder>))*?(?(open)(?!))</folder>

演示

我们从请求的标签开始:<folder>

现在不是<folder></folder>: (?:(?!</?folder>).)*

接下来我们要找的是:<id=2>

然后是.*直到结束符号:</folder>

问题是某些可以包含开始和结束令牌。这一点必须被抓住。最好的方法是使用平衡组定义。有了这个,我们就可以匹配,直到找到结束标记。.*必须是令牌的BGD: (?:(?!</?folder>).|(?<open><folder>)|(?<-open></folder>))*?(?(open)(?!))

关于BGD的一个很好的介绍是在这里和这里