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