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

时间:2017-02-05 11:52:12

标签: .net regex regex-lookarounds

我发布了this question的答案,其中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 } }使用积极的前瞻项目 - 或者我需要使用不同的东西吗?

1 个答案:

答案 0 :(得分:1)

您不需要积极的前瞻,使用捕获和堆叠条件检查:

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

请参阅regex demo

的POI:

  • layer\s*{(?<f>\s*foo)? - 添加了一个可选的命名组“f”,可以在foo +可选的空格数后显示layer {
  • (?>{\s*foo(?<f>)(?<c>)| - 原子组内的第一个分支是一个与{(节点的开头)匹配的分支,后跟foo,如果匹配,则有2个堆栈递增:f(foo组)和c(开括号组)。
  • (?(f)|(?!)) - 在检查了{}的平衡数后,此条件结构检查foo堆栈是否为空,如果它不为空,则一切正常,返回匹配,否则匹配失败。