在Ruby中实现平衡的括号正则表达式

3

我发现了 Ruby 编程语言的《Programming Ruby》这本书中有一个正则表达式,可以用来查找平衡的花括号表达式。我正在尝试在此基础上构建一个能够匹配平衡的大括号、中括号和小括号的正则表达式。

原始正则表达式:

re = /
  \A
    (?<brace_expression>
      {
        (
          [^{}]                 # anything other than braces
        |                       # ...or...
          \g<brace_expression>  # a nested brace expression
        )*
      }
    )
  \Z
/x

到目前为止,我的版本如下:

re = /
  \A
    (?<brace_expression>
      (?:
        (?<brace> { ) | (?<bracket> \[ ) | ( \( )
      )
        (
          [^{}\[\]()]           # anything other than braces
        |                       # ...or...
          \g<brace_expression>  # a nested brace expression
        )*
      (?(<brace>) } | (?(<bracket>) \] | \) ) )
    )
  \Z
/x

它能正确匹配 "{xyz}", "[xyz]", "(xyz)", 并正确地不匹配诸如 "{xyz]" 的内容,但递归的行为并不像我预期的那样。它无法匹配嵌套的大括号表达式,例如 "{[]}"。我错过了什么吗?
1个回答

2

有趣的问题。您当前的模式看起来非常不错。考虑使用替代方案而不是条件语句,因为在与递归一起使用时似乎不可靠。

re = /
  \A(                            # start group 1
    \(([^)(\]\[}{]+|\g<1>)*+\)|  # parens & set group 2
    \[\g<2>*+\]|                 # brackets
    \{\g<2>*+\}                  # braces
  )\z                            # group 1 end
/x
  • \g<1> 是对第一个分组进行 子表达式调用,该分组包含开头和结尾之间的模式。
  • \g<2> 是对第二个分组进行调用,该分组包含 [^)(\]\[}{]+|\g<1> 以进行模式缩减,详见 此处
  • *+ 是一种 占有性 量词,如果失衡可以提高匹配失败的性能。

在Regex101上(PCRE)查看示例 或者 Rubular v1.9.3+


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接