具有平衡组的正则表达式适用于负前瞻但不适用于正前瞻(.net 方言)

Regex with balancing groups works with negative lookahead but not positive lookahead (.net dialect)

我发布了 的答案,其中 OP 希望正则表达式匹配不同的 JSON-esque 数据块,条件是其中一个属性具有特定值。

稍微简化一下问题 - 假设一些示例数据如下:

layer { foo { bar { baz } } qux }
layer { fee { bar { baz } } qux }
layer { foo { bar { baz foo } } qux { quux quuux } }
{}
zip { layer { zop { layer {yeehah { foo } } } } }
zip { layer{ zop { layer {yeehah { fee } } } } }

正则表达式应匹配 layer { .. stuff with nested data ...},但仅在存在数据元素 foo 的情况下。

我在答案中的正则表达式是:

layer\s*{(?>{(?<c>)|[^{}](?!fee)+|}(?<-c>))*(?(c)(?!))}

这不是积极识别包含 foo 的匹配,而是排除包含 fee 的匹配。如果所有非 fee 项目都是 foo 项目,那很好,但另一个线程上的问题并非如此。我的解决方案基本上是将所有其他非 foo 项目添加到负面前瞻中,如下所示:

layer\s*{(?>{(?<c>)|[^{}](?!fee|blah|bloh|bluh|etc)+|}(?<-c>))*(?(c)(?!))}

但如果您事先不知道要排除的数据项,这是不切实际的。我尝试使用正面前瞻:

layer\s*{(?>{(?<c>)|[^{}](?=foo)+|}(?<-c>))*(?(c)(?!))}

但这不起作用。

我的问题:谁能帮我重写正则表达式以匹配例如layer { foo { bar } } 个项目通过使用积极的前瞻性 - 还是我需要使用不同的东西?

您不需要正面前瞻,使用捕获和堆栈条件检查:

layer\s*{(?<f>\s*foo)?(?>{\s*foo(?<f>)(?<c>)|{(?<c>)|[^{}]+|}(?<-c>))*(?(c)(?!))(?(f)|(?!))}

regex demo

兴趣点:

  • layer\s*{(?<f>\s*foo)? - 添加一个可选的命名组 "f",如果在 layer { + 可选的空格数之后存在,则捕获 foo
  • (?>{\s*foo(?<f>)(?<c>)| - 原子组内的第一个分支是与 {(节点的开始)匹配的分支,后跟 foo,如果匹配,则为 2堆栈递增:f(foo 组)和 c(左大括号组)。
  • (?(f)|(?!)) - 检查完 {} 的平衡数后,这个条件构造检查 foo 栈是否不为空,如果不为空,则所有OK则返回匹配,否则匹配失败