【问题标题】:Regex for nested XML attributes嵌套 XML 属性的正则表达式
【发布时间】:2016-05-09 10:24:58
【问题描述】:

假设我有以下字符串:

"<aa v={<dd>sop</dd>} z={ <bb y={ <cc x={st}>ABC</cc> }></bb> }></aa>"

如何编写通用正则表达式(标签名称更改,属性名称更改)以匹配 {} 中的内容,<dd>sop</dd><bb y={ <cc x={st}>ABC</cc> }></bb>

我写的正则表达式 "(\s*\w*=\s*\{)\s*(<.*>)\s*(\})" 匹配

"<dd>sop</dd>} z={ <bb y={ <cc x={st}>ABC</cc> }></bb>" 不正确。

【问题讨论】:

    标签: regex recursive-regex


    【解决方案1】:

    在通用正则表达式中,没有办法很好地处理嵌套。因此,当出现这样的问题时,所有的胜利 - 永远不要使用正则表达式来解析 XML/HTML。

    在一些简单的情况下,它可能是有利的。如果像在您的示例中那样,嵌套级别数量有限,您可以非常简单地为每个级别添加一个正则表达式。

    现在让我们分步进行。要处理第一个未嵌套的属性,您可以使用

    {[^}]*}
    

    这匹配一个起始大括号,后跟任意数量的,但是一个右大括号,最后是一个右大括号。为简单起见,我将把它的核心放在一个非捕获组中,比如

    {(?:[^}])*}
    

    这是因为在插入备用的时,它是必需的。

    如果您现在允许 除右大括号以外的任何内容 ([^}]) 也成为另一个嵌套级别的大括号​​,只需加入第一个正则表达式,例如

    {(?:{[^}]*}|[^}])*}
        ^^^^^^^    original regex inserted as alternative (to it self)
    

    它允许一层嵌套。再次做同样的事情,加入这个正则表达式来替代它自己,比如

    {(?:{(?:{[^}]*}|[^}])*}|{[^}]*}|[^}])*}
            ^^^^^^^^^^^^^^^    previous level repeated
    

    将允许另一个级别的嵌套。如果需要,可以对更多级别重复此操作。

    这不处理属性名称和东西的捕获,因为你的问题不是很清楚你想要什么,但它向你展示了一种方式(我最容易理解,或者......:P ) 来处理正则表达式中的嵌套。

    You can see it handle your example here at regex101.

    问候

    【讨论】:

    • 感谢您的出色回答。我会注意到 {} 应该转义为 \{ \}
    • 据我所知,这实际上没有必要。如果它不采用量词的形式,它会从字面上匹配它们。但为了可读性 - 你的权利。
    • 已检查,Java 似乎是上述情况的例外;)
    【解决方案2】:

    您正在尝试处理一组平衡的大括号。这需要递归正则表达式。根据定义,递归正则表达式不是规则的。无论如何,有些语言支持它们,例如Perl、PHP、红宝石。 This 是一个很好的主题教程。

    通常,您应该使用成熟的解析器(例如 yacc)来提取此类信息。

    这是一个可以处理非平衡大括号的正则表达式:([ =]*)=(\{[^}]*\})。这将匹配{<dd>sop</dd>}{st},这是正确的。不幸的是,它也会匹配{ <bb y={ <cc x={st},这不是您想要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-04
      • 2011-07-18
      • 1970-01-01
      • 1970-01-01
      • 2013-08-12
      • 2013-12-05
      • 1970-01-01
      相关资源
      最近更新 更多