Почему конструкторы регулярных выражений должны быть дважды экранированы?

В приведенном ниже выражении \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!