Почему конструкторы регулярных выражений должны быть дважды экранированы?
В приведенном ниже выражении \s
обозначает пробельный символ. Я представляю, что парсер регулярных выражений проходит через строку и видит \
и знает, что следующий символ является особенным.
Но это не тот случай, когда требуются двойные экраны.
Почему это?
var res = new RegExp('(\\s|^)' + foo).test(moo);
Есть ли конкретный пример того, как один побег может быть неправильно интерпретирован как что-то еще?
Ответы
Ответ 1
Вы создаете регулярное выражение, передавая строку в конструктор RegExp.
\
является escape-символом в строковых литералах.
\
используется синтаксическим анализом строкового литерала…
const foo = "foo";
const string = '(\s|^)' + foo;
console.log(string);
Ответ 2
Внутри кода, в котором вы создаете строку, обратная косая черта сначала является символом escape-кода javascript, что означает, что escape-последовательности, такие как \t
, \n
, \"
и т.д., будут переведены в их javascript-аналог (вкладка, новая строка, цитата и т.д.), и это будет сделано частью строки. Двойная обратная косая черта представляет собой одиночную обратную косую черту в самой строке, поэтому, если вам нужна обратная косая черта в строке, вы сначала избегаете ее.
Итак, когда вы создаете строку, говоря var someString = '(\\s|^)'
, то, что вы действительно делаете, создает фактическую строку со значением (\s|^)
.
Ответ 3
Regex нуждается в строчном представлении \s
, который в JavaScript может быть создан с использованием литерала "\\s"
.
Вот живой пример, чтобы проиллюстрировать, почему "\s"
недостаточно:
alert("One backslash: \s\nDouble backslashes: \\s");
Ответ 4
\ используется в строках для вызова специальных символов. Если вам нужна обратная косая черта в вашей строке (например, для \in\s), вам нужно избежать ее с помощью обратного слэша. Итак\становится \\.
EDIT: Даже нужно было сделать это здесь, потому что\\в моем ответе обратился к \.
Ответ 5
Как уже было сказано, внутри строкового литерала обратная косая черта указывает escape-последовательность, а не буквальный символ обратной косой черты, но конструктору RegExp часто требуются литеральные символы обратной косой черты в передаваемой ему строке, поэтому код должен иметь \\
для представления буквальная обратная косая черта, в большинстве случаев.
Проблема в том, что двойные экранированные метасимволы утомительны. Есть один способ передать строку в new RegExp
без необходимости двойного экранирования: используйте шаблонный тег String.raw
, особенность ES6, которая позволяет вам написать строку, которая будет дословно проанализирована интерпретатором, без какого-либо анализа escape-последовательностей. Например:
console.log('\\'.length); // length 1: an escaped backslash
console.log('\\'.length); // length 1: an escaped backslash
console.log(String.raw'\\'.length); // length 2: no escaping in String.raw!