我在以下正则表达式中找到了它:
\[(?:[^][]|(?R))*\]
它将方括号(及其内容)与嵌套的方括号匹配。
[^][]
是一个字符类,表示除[
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]
的字符。要拥有a
and ]
,您必须编写:[^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)[^][]*)*+])
这避免了交替的成本。