Во-первых, давайте отбросим обратную косую черту. [
и ]
не являются специальными для строк (*), и, следовательно, экранирование их не меняет их. Таким образом, следующее эквивалентно и легче для чтения:
(string-match "[][]" "[") ; ===> 0
(string-match "[][]" "]") ; ===> 0
(string-match "[][]" "[]") ; ===> 0
(string-match "[][]" "][") ; ===> 0
(string-match "[][]" "][") ; ===> 0
Этот шаблон соответствует либо ]
, либо [
, и все тестируемые строки имеют один из этих символов в начале; следовательно, мы совпадаем в позиции 0
в каждом случае.
Критически, чтобы включить ]
в альтернативу символа, должен быть первым символом. Следовательно следующее не делает то, что вы хотели:
(string-match "[[]]" "[") ; ===> nil
(string-match "[[]]" "]") ; ===> nil
(string-match "[[]]" "[]") ; ===> 0
Этот шаблон в точности совпадает с []
, поскольку [[]
- это символьная альтернатива, соответствующая чему-либо в наборе, состоящем из одного символа [
; и за этой символьной альтернативой следует ]
(которая, когда не заканчивает символьную альтернативу, просто совпадает с собой).
Вы можете прочитать подробности "альтернативы персонажу" по адресу:
C-h i g (elisp)Regexp Special
RET
<Ч />
(*) Обратите внимание, что обратные слэши не являются специальными для регулярного выражения, когда они в пределах альтернативы символа.
У ваших регулярных выражений не было обратной косой черты - потому что в строковом формате с двойными кавычками вам нужно было бы удвоить обратную косую черту, чтобы включить их в регулярное выражение - но если бы вы это сделали, и если бы они были также внутри альтернативы символа, это будет означать, что обратный слеш будет одним из символов, соответствующих этому набору.
например. "[\\]\\[]"
- это регулярное выражение [\]\[]
, которое соответствует \[]
(Помните, что ]
не может появиться в альтернативе символа, если это не первый символ.)