Экранирование, специальные символы

Как мы уже видели, обратная косая черта "\" используется для обозначения классов символов. Это специальный символ в регулярных выражениях (как и в обычных строках).

Есть и другие специальные символы, которые имеют особое значение в регулярном выражении. Они используются для более сложных поисковых конструкций. Вот полный перечень этих символов: [ \ ^ $ . | ? * + ( ).

Не надо пытаться запомнить этот список – скоро мы разберёмся с каждым из них по отдельности, и таким образом вы выучите их «автоматически».

Экранирование символов

Допустим, мы хотим найти буквально точку. Не «любой символ», а именно точку.

Чтобы использовать специальный символ как обычный, добавьте к нему обратную косую черту: \..

Это называется «экранирование символа».

К примеру:

alert( "Глава 5.1".match(/\d\.\d/) ); // 5.1 (совпадение!)
alert( "Глава 511".match(/\d\.\d/) ); // null ("\." - ищет обычную точку)

Круглые скобки также являются специальными символами, поэтому, если нам нужно использовать именно их, нужно указать \(. В приведённом ниже примере ищется строка "g()":

alert( "function g()".match(/g\(\)/) ); // "g()"

Если мы ищем обратную косую черту \, это специальный символ как в обычных строках, так и в регулярных выражениях, поэтому мы должны удвоить её.

alert( "1\\2".match(/\\/) ); // '\'

Косая черта

Символ косой черты '/' не является специальным символом, но в JavaScript он используется для открытия и закрытия регулярного выражения: /...pattern.../, поэтому мы должны экранировать его.

Вот как выглядит поиск самой косой черты '/':

alert( "/".match(/\//) ); // '/'

С другой стороны, если мы не используем короткую запись /.../, а создаём регулярное выражение, используя new RegExp, тогда нам не нужно экранировать косую черту:

alert( "/".match(new RegExp("/")) ); // '/'

new RegExp

Если мы создаём регулярное выражение с помощью new RegExp, то нам не нужно учитывать /, но нужно дополнительное экранирование.

Рассмотрим такой пример:

let reg = new RegExp("\d\.\d");

alert( "Глава 5.1".match(reg) ); // null

Поиск работает с /\d\.\d/, но не работает с new RegExp("\d\.\d"), почему?

Причина в том, что символы обратной косой черты «съедаются» строкой. Как вы помните, что обычные строки имеют свои специальные символы, такие как \n, и для экранирования используется обратная косая черта.

Вот как воспринимается строка «\d.\d»:

alert("\d\.\d"); // d.d

Кавычки «съедают» символы обратной косой черты для себя, например:

  • \n – становится символом перевода строки,
  • \u1234 – становится символом Юникода с указанным номером,
  • …А когда нет особого значения: как например для \d или\z, обратная косая черта просто удаляется.

Таким образом, вызов new RegExp получает строку без обратной косой черты. Вот почему поиск не работает!

Чтобы исправить это, нам нужно удвоить обратную косую черту, потому что кавычки превращают \\ в \:

let regStr = "\\d\\.\\d";
alert(regStr); // \d\.\d (теперь правильно)

let reg = new RegExp(regStr);

alert( "Глава 5.1".match(reg) ); // 5.1

Итого

  • Для поиска специальных символов [ \ ^ $ . | ? * + ( ) в буквальном смысле, нам нужно добавить перед ними \ («экранировать их»).
  • Нам также нужно экранировать /, если мы используем /.../ (но не new RegExp).
  • При передаче строки в new RegExp нужно удвоить обратную косую черту \\ для экранирования специальных символов, потому что строки будут использовать одну из них для своих целей.
Карта учебника

Комментарии

перед тем как писать…
  • Если вам кажется, что в статье что-то не так - вместо комментария напишите на GitHub.
  • Для одной строки кода используйте тег <code>, для нескольких строк кода — тег <pre>, если больше 10 строк — ссылку на песочницу (plnkr, JSBin, codepen…)
  • Если что-то непонятно в статье — пишите, что именно и с какого места.