Ответ 1
[^][]
- это класс символов, который означает все символы, кроме [
и ]
.
Вы можете избежать экранирования специальных символов [
и ]
, поскольку это не является двусмысленным для PCRE, механизма регулярных выражений, используемого в preg_
.
Так как [^]
неверно в PCRE, единственный способ для синтаксического анализа регулярных выражений состоит в том, что ]
находится внутри класса символов, который будет закрыт позже. То же самое с [
. Он не может повторно открыть класс символов (кроме символьного класса POSIX [:alnum:]
) внутри класса символов. Тогда последний ]
понятен; это конец класса символов. Однако a [
вне класса символов должен быть экранирован, так как он анализируется как начало класса символов.
Таким же образом вы можете написать []]
или [[]
или [^[]
без экранирования [
или ]
в классе символов.
Вы можете использовать этот синтаксис с несколькими регулярными выражениями: PCRE (PHP, R), Perl, Python, Java,.NET, GO, awk, Tcl (если вы разделите свой рисунок фигурными скобками, спасибо Donal Fellows)...
Но не с: Ruby, JavaScript (кроме IE < 9),...
Как отмечал m.buettner, [^]]
не является двусмысленным, поскольку ]
является символом first, [^a]]
рассматривается как все, что не является a
, за которым следует ]
. Чтобы иметь a
и ]
, вы должны написать: [^a\]]
или [^]a]
В частном случае JavaScript спецификация позволяет []
как токен регулярного выражения, который никогда не совпадает (другими словами, []
всегда терпит неудачу) и [^]
как регулярное выражение, которое соответствует любому символу. Тогда [^]]
рассматривается как любой символ, за которым следует a ]
. Фактическая реализация меняется, но современный браузер обычно придерживается определения в спецификации.
Сведения о шаблоне:
\[ # 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)[^][]*)*+])
, что позволяет избежать затрат на чередование.