【问题标题】:Regex to ignore matches on nested delimeters正则表达式忽略嵌套分隔符上的匹配
【发布时间】:2013-12-01 10:16:30
【问题描述】:

我有一个输入字符串如下:

var format = "{0}({1:2}({*:8})){2:3}({3:16})";

对于“你这样做是为了什么”的问题
上面的格式告诉我们的很像 string.Format(string, args) 方法,只是做了一些修改。

  • {0} 是插入索引
  • {1:2} 是一个以字节为单位指定长度的插入索引
  • ({3:16}) 是分组插入索引,保留匹配序列的副本

预期输出图:

  • {0}
  • ({1:2}({*:8}))
  • {2:3}
  • ({3:16})

我现在得到的:

  • {0}
  • ({1:2}
  • ({*:8}))
  • {2:3}
  • ({3:16})

我现在使用的正则表达式:

var regExpr = @"\(?\{\(*([^/}]+)\)*\}\)?";

顺便说一句,由于我刚刚学习RegEx,所以我希望 cmets 了解表达式的效率。

【问题讨论】:

    标签: c# .net regex


    【解决方案1】:

    好吧,我想我找到了一个解决方案 - 这可能是一个非常低效的匹配模式,但我对它是否可以完成很感兴趣:

    (((?<r>\{)|(?<-r>\})|(?<b>\()|(?<-b>\))|[^{}()]))+?(?(r)(?!))(?(b)(?!))
    

    Working On RegexHero(.NET 正则表达式测试器)Also tested here

    解释

    首先我们有(?&lt;r&gt;\{)|(?&lt;-r&gt;\})|(?&lt;b&gt;\()|(?&lt;-b&gt;\)

    这些是平衡组。对于每个找到的{,它将匹配添加到r 组,然后对于每个},它从r 组中删除该匹配。 b 组中的 () 也是如此。

    然后替换的最后一部分是[^{}()],它匹配其他所有内容 - 即任何可能出现在括号之间的内容。

    最后我们有了(?(r)(?!))(?(b)(?!))(您也许可以使用(?(r|b)(?!)),但它搞砸了我使用的2 个测试仪中的1 个的结果)。这是一个if..then 构造,它检查rb 组中是否有任何内容,如果有则(?!) - 一个否定的前瞻,它总是返回false。如果括号不平衡,这会使匹配返回 false。

    由于交替后的+ 是懒惰的+?,它将匹配保持括号平衡的最短段。

    至少在 RegexHero 上匹配:

    \1 {0}
    \2 ({1:2}({*:8}))
    \3 {2:3}
    \4 ({3:16})
    

    【讨论】:

    • 不能保证这适用于 C#,RegexHero 是我必须测试的最接近的东西。
    • 我担心这会变得有些复杂。谢谢,这似乎可以满足我的需要。
    【解决方案2】:

    这通常无法使用正则表达式,但请阅读 .NET 中的 Balancing Group Definition 扩展。

    【讨论】:

    • really? - 我不是想成为一个聪明人,我不使用 .net,但这个答案不是暗示吗?
    • @OGHaza 见this question
    • 好吧,我不想立即匹配嵌套的“分组”。我只想要外部匹配。
    • 我并没有真正理解这篇文章所传达的关于平衡组定义的内容。
    • @KonradKokosa,如果您阅读有关该问题的进一步答案,则表明 .NET 是能够执行此类任务的众多正则表达式引擎之一。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多