Обратные ссылки в шаблоне: \n и \k

Доступ к содержимому скобочных групп есть не только в результате или в строке замены, но и в самом шаблоне.

Обратная ссылка по номеру: \n

К группе можно обратиться в шаблоне, используя \n, где \n – это номер группы.

Чтобы было яснее, рассмотрим это на следующем примере.

Необходимо найти в тексте строку в кавычках: либо одинарных'...', либо двойных "..." – оба варианта должны работать.

Как найти такие строки?

Можно добавить оба вида кавычек в квадратные скобки: ['"](.*?)['"], но в таком случае будут находиться строки со смешанными кавычками, например "...' и '...". Это приведёт к ошибке, когда одна кавычка окажется внутри других, как в строке "She's the one!":

let str = `He said: "She's the one!".`;

let reg = /['"](.*?)['"]/g;

// Результат не соответствует замыслу
alert( str.match(reg) ); // "She'

Как видно, шаблон нашёл открывающую кавычку ", а после нашёл текст вплоть до следующей кавычки ', после чего поиск завершился.

Для того, чтобы шаблон искал закрывающую кавычку такую же, как и открывающую, обернём открывающие кавычки в скобочную группу и используем обратную ссылку на неё:

Вот верный код:

let str = `He said: "She's the one!".`;

let reg = /(['"])(.*?)\1/g;

alert( str.match(reg) ); // "She's the one!"

Теперь работает! Движок регулярных выражений находит первую кавычку из шаблона (['"]) и запоминает её. Это первая скобочная группа.

Далее в шаблоне \1 означает «найти то же самое, что в первой скобочной группе», а именно – аналогичную кавычку в нашем случае.

Обратите внимание на два нюанса:

  • Чтобы использовать скобочную группу в строке замены, нужно использовать ссылку вида $1, а в шаблоне – обратный слэш: \1.
  • Мы не можем обращаться к группе, если в ней используется ?:. Группы, которые помечены (?:...), не запоминаются движком.

Обратная ссылка по имени: \k<name>

Обратные ссылки с помощью \k<name> возможны для именованных групп.

Ниже пример с именованной группой:

let str = `He said: "She's the one!".`;

let reg = /(?<quote>['"])(.*?)\k<quote>/g;

alert( str.match(reg) ); // "She's the one!"
Карта учебника

Комментарии

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