Как работает экранирование в литерале регулярного выражения JS?
Узнал про литералы regexp в JS и решил попробовать. Насколько я понимаю, отличий между написанием регулярного выражение как строки и как литерала всего три:
- В литерале не требуется дополнительного экранирования слэшей
// - Литерал неизменяем
- В литерале можно использовать дополнительные опции (например буква g, которая задаёт глобальный поиск)
И вот у меня была регулярка:
const regexp = '\\[[^\\[\\]]*\\]';
let str = '[image|variant][image|variant][image|variant]';
let results = [...str.matchAll(regexp)];
alert(results[0]);
И я решил поменять её на такой литерал: /\[[^\[\]]*\]/g. Он корректно работает, но WebStorm почему-то настойчиво предлагает мне удалить экранирование для последней квадратной скобки. Я попробовал, и такой вариант тоже работает: /\[[^\[\]]*]/g.
Почему последнюю квадратную скобку можно не экранировать? Есть ли какие-то чёткие правила по этому поводу?
UPD: Любопытно, что это работает только с квадратными скобками. Я решил проверить, можно ли не экранировать последнюю скобку, если она будет круглой: /\([^\[\]]*)/g, но такой литерал не валиден и вызывает ошибку.
Ответы (2 шт):
@vsemozhebuty привел ссылку, в которой содержался ответ на вопрос. Начать следует с того, что там приводится список специальных символов, используемых в regexp:
Есть и другие специальные символы, которые имеют особое значение в регулярном выражении. Они используются для более эффективного поиска. Вот полный список из них:
[ \ ^ $ . | ? * + ( ).
Следует обратить внимание, что закрывающей квадратной скобки ] в этом списке нет, зато есть закрывающая круглая скобка ), что отвечает на мой вопрос о том, почему закрывающую квадратную скобку не надо экранировать, а круглую надо.
Однако в моём regexp комбинация из квадратных скобок как символов используется дважды:
/\[[^\[\]]*]/g
// последняя квадратная скобка не экранирована (3 символ справа)
// другую закрывающую квадратную скобку приходится всё так же экранировать (6 символ справа)
И квадратную скобку, которая идёт шестым символом справа, приходится по-прежнему экранировать, иначе она начинает считаться не скобкой-символом, а управляющей скобкой, которая закрывает диапазон. Конкретно про такую ситуацию по ссылке ничего нет, но в данном случае нужда в экранировании выглядит логично (иначе интерпретатор просто неверно истолкует regexp).
P.S.: Сначала я решил, что это просто причуды JS, этот язык очень любит меня удивлять. Но, оказывается, ситуация с закрывающей квадратной скобкой ] является нормальной для регулярных выражений вообще, а не только в JS. По крайней мере так мне говорит regex101. Это забавно.
