Ответ 1
Позвольте сломать его:
[]-a-z]
^^ ^
|| +---- 3
|+------ 2
+------- 1
1
является литералом ]
, поскольку он появляется в начале шаблона, а []
является недопустимым символьным классом в PCRE.
Таким образом, 2
дефис является вторым символом в классе и вводит диапазон между ]
и a
.
Следующий дефис 3
обрабатывается буквально, потому что предыдущий токен a
- это конец предыдущего диапазона. Другой диапазон не может быть введен в этот момент. В PCRE a -
обрабатывается буквально, если он находится в месте, где диапазон не может быть введен или если он сбежал. Мы обычно размещаем буквальные дефисы в начале или в конце диапазона, чтобы сделать это очевидным, но это не требуется.
Тогда z
- простой литерал.
PCRE следует за синтаксисом Perl. Это документировано следующим образом:
О ]
:
A
]
обычно является либо концом класса символов POSIX (см. ниже приведенные ниже классы символов POSIX), либо он сигнализирует о конце класса символов в квадратных скобках. Если вы хотите включить]
в набор символов, вы, скорее всего, избежите его.
Однако, если]
является первым символом (или вторым, если первый символ является символом каретки) символьного символьного класса, он не обозначает конец класса (поскольку вы не можете пустой класс) и считается частью набора символов, которые могут быть сопоставлены без экранирования.
О дефисах:
Если дефис в символьном классе не может синтаксически быть частью диапазона, например, потому что он является первым или последним символом класса символов, или если он сразу следует за диапазон, дефис не является особым, и поэтому считается символом, который должен соответствовать буквально. Если вы хотите, чтобы дефис в вашем наборе символов был сопоставлен, а его позиция в классе такова, что его можно считать частью диапазона, вы должны избежать этого дефиса с обратным слэшем.
Обратите внимание, что это относится к синтаксису Perl. Другие вкусы могут иметь другое поведение. Например, []
является допустимым (пустым) символьным классом в JavaScript, который ничего не может сопоставить.
Ловушка заключается в том, что в зависимости от параметров PCRE также может интерпретировать это в JS-режиме (там есть несколько флагов совместимости JS). Из PCRE2 docs:
Открывающая квадратная скобка вводит класс символов, заканчивающийся закрывающей квадратной скобкой. Закрывающая квадратная скобка сама по себе не является особенной по умолчанию. Если в качестве члена класса требуется закрывающая квадратная скобка, она должна быть первым символом данных в классе (после начального обводки, если он есть) или экранированным обратным слэшем. Это означает, что по умолчанию пустой класс не может быть определен. Однако, если параметр
PCRE2_ALLOW_EMPTY_CLASS
установлен, закрывающая квадратная скобка в начале заканчивает (пустой) класс.
Зарегистрированное поведение PCRE в отношении дефиса, неудивительно, соответствует поведению Perl:
Символ минус (дефис) может использоваться для указания диапазона символов в классе символов. Например,
[d-m]
соответствует любой букве между d и m включительно. Если в классе требуется минус-символ, он должен быть экранирован с помощью обратного слэша или появится в позиции, где его нельзя интерпретировать как указание диапазона, как правило, в качестве первого или последнего символа в классе, или сразу после диапазона. Например,[b-d-z]
соответствует буквам в диапазоне отb
доd
, символу дефиса илиz
.