Регулярные выражения – мощное средство поиска и замены в строке.
В JavaScript регулярные выражения реализованы отдельным объектом RegExp и интегрированы в методы строк.
Регулярные выражения
Регулярное выражение (оно же «регэксп», «регулярка» или просто «рег»), состоит из шаблона (также говорят «паттерн») и необязательных флагов.
Существует два синтаксиса для создания регулярного выражения.
«Длинный» синтаксис:
regexp = new RegExp("шаблон", "флаги");
…И короткий синтаксис, использующий слеши "/"
:
regexp = /шаблон/; // без флагов
regexp = /шаблон/gmi; // с флагами gmi (будут описаны далее)
Слеши /.../
говорят JavaScript о том, что это регулярное выражение. Они играют здесь ту же роль, что и кавычки для обозначения строк.
Регулярное выражение regexp
в обоих случаях является объектом встроенного класса RegExp
.
Основная разница между этими двумя способами создания заключается в том, что слеши /.../
не допускают никаких вставок переменных (наподобие возможных в строках через ${...}
). Они полностью статичны.
Слеши используются, когда мы на момент написания кода точно знаем, каким будет регулярное выражение – и это большинство ситуаций. А new RegExp
– когда мы хотим создать регулярное выражение «на лету» из динамически сгенерированной строки, например:
let tag = prompt("Какой тег вы хотите найти?", "h2");
let regexp = new RegExp(`<${tag}>`); // то же, что /<h2>/ при ответе "h2" на prompt выше
Флаги
Регулярные выражения могут иметь флаги, которые влияют на поиск или предоставляют дополнительную информацию.
В JavaScript их всего семь:
i
- С этим флагом поиск не зависит от регистра: нет разницы между
A
иa
(см. пример ниже). g
- С этим флагом поиск ищет все совпадения, без него – только первое.
m
- Многострочный режим (рассматривается в главе Многострочный режим якорей ^ $, флаг "m").
s
- Включает режим «dotall», при котором точка
.
может соответствовать символу перевода строки\n
(рассматривается в главе Символьные классы). u
- Включает полную поддержку Юникода. Флаг разрешает корректную обработку суррогатных пар (подробнее об этом в главе Юникод: флаг "u" и класс \p{...}).
y
- Режим поиска на конкретной позиции в тексте (описан в главе Поиск на заданной позиции, флаг "y").
d
- С этим флагом результат регулярного выражения помещается в массив, который содержит дополнительную информацию о регулярном выражении, например индексы начала и конца подстрок. Этот флаг не меняет поведение регулярного выражения, а лишь предоставляет дополнительную информацию.
Здесь и далее в тексте используется следующая цветовая схема:
- регулярное выражение –
красный
- строка (там где происходит поиск) –
синий
- результат –
зелёный
Поиск: str.match
Как уже говорилось, использование регулярных выражений интегрировано в методы строк.
Метод str.match(regexp)
для строки str
возвращает совпадения с регулярным выражением regexp
.
У него есть три режима работы:
-
Если у регулярного выражения есть флаг
g
, то он возвращает массив всех совпадений:let str = "Любо, братцы, любо!"; alert( str.match(/любо/gi) ); // Любо,любо (массив из 2х подстрок-совпадений)
Обратите внимание: найдены и
Любо
илюбо
, благодаря флагуi
, который делает регулярное выражение регистронезависимым. -
Если такого флага нет, то возвращает только первое совпадение в виде массива, в котором по индексу
0
находится совпадение, и есть свойства с дополнительной информацией о нём:let str = "Любо, братцы, любо!"; let result = str.match(/любо/i); // без флага g alert( result[0] ); // Любо (первое совпадение) alert( result.length ); // 1 // Дополнительная информация: alert( result.index ); // 0 (позиция совпадения) alert( result.input ); // Любо, братцы, любо! (исходная строка)
В этом массиве могут быть и другие индексы, кроме
0
, если часть регулярного выражения выделена в скобки. Мы разберём это в главе Скобочные группы. -
И, наконец, если совпадений нет, то, вне зависимости от наличия флага
g
, возвращаетсяnull
.Это очень важный нюанс. При отсутствии совпадений возвращается не пустой массив, а именно
null
. Если об этом забыть, можно легко допустить ошибку, например:let matches = "JavaScript".match(/HTML/); // = null if (!matches.length) { // Ошибка: у null нет свойства length alert("Ошибка в строке выше"); }
Если хочется, чтобы результатом всегда был массив, можно написать так:
let matches = "JavaScript".match(/HTML/) || []; if (!matches.length) { alert("Совпадений нет"); // теперь работает }
Замена: str.replace
Метод str.replace(regexp, replacement)
заменяет совпадения с regexp
в строке str
на replacement
(все, если есть флаг g
, иначе только первое).
Например:
// без флага g
alert( "We will, we will".replace(/we/i, "I") ); // I will, we will
// с флагом g
alert( "We will, we will".replace(/we/ig, "I") ); // I will, I will
В строке замены replacement
мы можем использовать специальные комбинации символов для вставки фрагментов совпадения:
Спецсимволы | Действие в строке замены |
---|---|
$& |
вставляет всё найденное совпадение |
$` |
вставляет часть строки до совпадения |
$' |
вставляет часть строки после совпадения |
$n |
если n это 1-2 значное число, вставляет содержимое n-й скобочной группы регулярного выражения, больше об этом в главе Скобочные группы |
$<name> |
вставляет содержимое скобочной группы с именем name , также изучим в главе Скобочные группы |
$$ |
вставляет символ "$" |
Пример с $&
:
alert( "Люблю HTML".replace(/HTML/, "$& и JavaScript") ); // Люблю HTML и JavaScript
Проверка: regexp.test
Метод regexp.test(str)
проверяет, есть ли хоть одно совпадение, если да, то возвращает true
, иначе false
.
let str = "Я ЛюБлЮ JavaScript";
let regexp = /люблю/i;
alert( regexp.test(str) ); // true
Далее в этом разделе мы будем изучать регулярные выражения, увидим ещё много примеров их использования, а также познакомимся с другими методами.
Полная информация о различных методах дана в главе Методы RegExp и String.
Итого
- Регулярное выражение состоит из шаблона и необязательных флагов:
g
,i
,m
,u
,s
,y
,d
. - Без флагов и специальных символов, которые мы изучим позже, поиск по регулярному выражению аналогичен поиску подстроки.
- Метод
str.match(regexp)
ищет совпадения: все, если есть флагg
, иначе только первое. - Метод
str.replace(regexp, replacement)
заменяет совпадения сregexp
наreplacement
: все, если у регулярного выражения есть флагg
, иначе только первое. - Метод
regexp.test(str)
возвращаетtrue
, если есть хоть одно совпадение, иначеfalse
.
Комментарии вернулись :)
<code>
, для нескольких строк кода — тег<pre>
, если больше 10 строк — ссылку на песочницу (plnkr, JSBin, codepen…)