41

我在以下正则表达式中找到了它:

\[(?:[^][]|(?R))*\]

它将方括号(及其内容)与嵌套的方括号匹配。

4

1 回答 1

68

[^][]是一个字符类,表示除[and之外的所有字符]

您可以避免转义[]特殊字符,因为它对于 PCRE(preg_函数中使用的正则表达式引擎)没有歧义。

由于[^]在 PCRE 中不正确,因此正则表达式解析的唯一方法]是在稍后将关闭的字符类中。下同[。它不能在字符类中重新打开字符类(POSIX 字符类除外[:alnum:])。然后最后一个]很清楚;这是字符类的结束。但是,[必须对字符类外部的字符进行转义,因为它被解析为字符类的开头。

同样,您可以在字符类中编写[]]or[[][^[]不转义[or 。]

注意:从 PHP 7.3 开始,您可以使用 inline xx 修饰符,即使在字符类中也可以忽略空白字符。这样你就可以用一种不那么模棱两可的方式来编写这些类:(?xx) [^ ][ ] [ ] ] [ [ ] [^ [ ].

您可以将此语法与几种正则表达式一起使用:PCRE (PHP, R), Perl, Python, Java, .NET, GO, awk, Tcl

但不适用于:Ruby、JavaScript(IE < 9 除外)、...

正如 m.buettner 所指出的,[^]]它并不模棱两可,因为]它是第一个字符,[^a]]被视为所有不是 aa后跟 a]的字符。要拥有aand ],您必须编写:[^a\]][^]a]

在 JavaScript 的特定情况下,规范允许[]作为一个从不匹配的正则表达式标记(换句话说,[]总是失败)和[^]一个匹配任何字符的正则表达式。然后[^]]被视为后跟一个的任何字符]。实际实现各不相同,但现代浏览器通常坚持规范中的定义。

图案细节:

\[          # literal [
(?:         # open a non capturing group
    [^][]   # a character that is not a ] or a [
  |         # OR
    (?R)    # the whole pattern (here is the recursion)
)*          # repeat zero or more time
\]          # a literal ]

在您的模式示例中,您不需要转义最后一个]

但是你可以对这个模式做同样的事情,稍微优化一下,更有用的原因是可以作为子模式重用(使用(?-1)(\[(?:[^][]+|(?-1))*+])

(                     # open the capturing group
    \[                # a literal [
        (?:           # open a non-capturing group
            [^][]+    # all characters but ] or [ one or more time
          |           # OR
            (?-1)     # the last opened capturing group (recursion)
                      # (the capture group where you are)
        )*+           # repeat the group zero or more time (possessive)
    ]                 # literal ] (no need to escape)
)                     # close the capturing group

或更好:(\[[^][]*(?:(?-1)[^][]*)*+])这避免了交替的成本。

于 2013-07-24T21:21:20.463 回答