我在下面的正则表达式中找到了它:
\[(?:[^][]|(?R))*\]
它匹配方括号(及其内容)以及嵌套的方括号。
[^][]
是一个字符类,表示除了[
和]
之外的所有字符。
由于PCRE不会产生歧义,因此可以避免转义[
和]
特殊字符,PCRE是在preg_
函数中使用的正则表达式引擎。
由于[^]
在PCRE中是不正确的,正则表达式只能解析]
在字符类内部并稍后被关闭的情况,[
也是同样的道理。它不能重新打开一个字符类(除了POSIX字符类[:alnum:]
)内部的字符类。然后最后的]
是清晰的,它是字符类的结尾。然而,字符类外部的[
必须转义,因为它被解析为字符类的开始。
同样地,您可以编写[]]
或[[]
或[^[]
,而无需转义字符类中的[
或]
。
注意:自PHP 7.3以来,您可以使用内联xx修饰符,即使在字符类内部也可以忽略空白字符。这样,您可以以较少的歧义方式编写这些类,例如:(?xx)[^ ][ ] [ ] ] [ [ ] [^ [ ]
。
您可以在多个正则表达式环境中使用此语法:PCRE(PHP,R),Perl,Python,Java,.NET,GO,awk,Tcl(如果使用花括号分隔模式,感谢Donal Fellows)等。
但是不能使用的环境包括:Ruby,JavaScript(除了IE<9)等。
正如m.buettner所指出的,[^]]
不会产生歧义,因为]
是第一个字符,[^a]]
被视为不是a
后跟]
的所有内容。要有a
和]
,必须写成:[^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)[^][]*)*+])
,它避免了使用选择分支所产生的代价。
]
出现在第一个字符位置(在否定符号之后),因为空字符类是不允许的。 - Martin Ender[^]
是有效的正则表达式(表示“任何字符”)。 - Tim Pietzcker[^]
的行为类似于PHP中本答案所示的方式。 - Izkata