КулЛиб - Классная библиотека! Скачать книги бесплатно
Всего книг - 716133 томов
Объем библиотеки - 1422 Гб.
Всего авторов - 275431
Пользователей - 125269

Новое на форуме

Новое в блогах

Впечатления

Masterion про Харников: Вечерний Чарльстон (Альтернативная история)

До Михайловского не дотягивает. Тема интересная, но язык тяжеловат.

2 Potapych
Хрюкнула свинья, из недостраны, с искусственным языком, самым большим достижением которой - самый большой трезубец из сала. А чем ты можешь похвастаться, ну кроме участия в ВОВ на стороне Гитлера, расстрела евреев в Бабьем Яру и Волыньской резни?.

Рейтинг: +1 ( 1 за, 0 против).
Lena Stol про Чернов: Стиратель (Попаданцы)

Хорошее фэнтези, прочитала быстро и с интересом.

Рейтинг: 0 ( 0 за, 0 против).
Влад и мир про серию История Московских Кланов

Прочитал первую книгу и часть второй. Скукота, для меня ничего интересно. 90% текста - разбор интриг, написанных по детски. ГГ практически ничему не учится и непонятно, что хочет, так как вовсе не человек, а высший демон, всё что надо достаёт по "щучьему велению". Я лично вообще не понимаю, зачем высшему демону нужны люди и зачем им открывать свои тайны. Живётся ему лучше в нечеловеческом мире. С этой точки зрения весь сюжет - туповат от

  подробнее ...

Рейтинг: 0 ( 0 за, 0 против).
DXBCKT про Дорин: Авиатор: Назад в СССР 2 (Альтернативная история)

Часть вторая продолжает «уже полюбившийся сериал» в части жизнеописания будней курсанта авиационного училища … Вдумчивого читателя (или слушателя так будет вернее в моем конкретном случае) ждут очередные «залеты бойцов», конфликты в казармах и «описание дубовости» комсостава...

Сам же ГГ (несмотря на весь свой опыт) по прежнему переодически лажает (тупит и буксует) и попадается в примитивнейшие ловушки. И хотя совершенно обратный

  подробнее ...

Рейтинг: +2 ( 2 за, 0 против).
DXBCKT про Дорин: Авиатор: назад в СССР (Альтернативная история)

Как ни странно, но похоже я открыл (для себя) новый подвид жанра попаданцы... Обычно их все (до этого) можно было сразу (если очень грубо) разделить на «динамично-прогрессорские» (всезнайка-герой-мессия мигом меняющий «привычный ход» истории) и «бытовые-корректирующие» (где ГГ пытается исправить лишь свою личную жизнь, а на все остальное ему в общем-то пофиг)).

И там и там (конечно) возможны отступления, однако в целом (для обоих

  подробнее ...

Рейтинг: +2 ( 2 за, 0 против).

Регулярные выражения для фронтендеров [Автор неизвестен] (pdf) читать онлайн

Книга в формате pdf! Изображения и текст могут не отображаться!


 [Настройки текста]  [Cбросить фильтры]

Регулярные выражения для
фронтендеров
HTML Academy
2021-11-30

Регулярные выражения для
фронтендеров
1. Основы регулярных выражений
1.1. Основные принципы регулярных выражений
1.2. Движение паттернов и возвраты
1.3. Атрибут pattern
1.4. Методы JavaScript для работы с регулярными
выражениями
1.5. Справочник
2. Первые селекторы
2.1. Одиночный символ
2.2. Чувствительность к регистру
2.3. Наборы символов
2.4. Экранирование символов
2.5. Отрицание
2.6. Границы текста
2.7. Рисуем смайлы
2.8. Рисуем смайлы (решение)
3. Символьные селекторы
3.1. Символьные селекторы
3.2. Служебные символы
3.3. Универсальный селектор
3.4. Оцифруемся
3.5. Оцифруемся (решение)
4. Группировка, условия, сохранение состояния и обратные
ссылки

4.1. Количество повторений
4.2. Сохранение совпадения
4.3. Группировка с условием ИЛИ
4.4. Отмена сохранения
4.5. Торжество лени
4.6. Торжество лени (решение)
4.7. Тест по пройденному материалу
4.7. Тест по пройденному материалу (ответы)
5. Квантификаторы. Ограничения длины. Жадность
5.1. Что если не?
5.2. Один или много +
5.3. Ни одного или много *
5.4. Жадность
5.5. Ограничение жадности
5.6. Опишем уровень игры
5.7. Опишем уровень игры (решение)
5.8. Тест по разделу квантификаторы
5.8. Тест по разделу квантификаторы (ответы)
6.
Опережающие
Модификаторы

и

ретроспективные

6.1. Позиционные проверки
6.2. Модификаторы
6.3. Триадам да
6.4. Триадам да (решение)
7. Хозяйке на заметку
7.1. Что не вошло?
7.2. Точность регулярных выражений
7.3. Скорость выполнения
7.4. Каскады правил
7.5. Регулярные выражения в среде окружения

проверки.

7.6. Финальный тест по программе курса
7.6. Финальный тест по программе курса (ответы)

1. Основы регулярных выражений
В первом разделе мы познакомимся с основными принципами
работы регулярных выражений, основными терминами.
Разберем механизм движения паттернов и возвраты. Вспомним
об атрибуте pattern=”” в элементах форм из курса HTML.
Познакомимся с методами JavaScript для работы с регулярными
выражениями.

1.1. Основные принципы регулярных
выражений
Прежде чем мы приступим к основной теме нашего курса,
обозначим маленькое условие: здесь и далее мы будем говорить
только о строке и строковых данных. Даже если речь идет о
числах, подразумеваем, что число преобразовано в формат
строки.
Итак, регулярные выражения — это формальный язык поиска
подстроки
в
строке.
Они
поддерживаются
многими
программами: редакторами, системными утилитами, базами
данных. Но особенно хорошо они раскрывают свои
возможности в языках программирования. В рамках курса мы
будем рассматривать регулярные выражения применительно к
языку JavaScript.

«

Историческая справка: регулярные выражения пришли к нам
из теории автоматов, которая является частью дискретной
математики.

Чтобы обозначить основную причину использования регулярных
выражений, поставим себе простую задачу:
Найти и заменить в строке Быстрее всего мы догоним ее на
машине местоимение ее на его .
Самым логичным способом было бы использовать прямую
замену:
'Быстрее всего мы догоним ее на машине'.replace('ее', 'его')

В нашем случае мы получим ожидаемо неверный результат: ее
является частью слова Быстрее , а .replace() заменит первое
вхождение подстроки.
Поэтому при решении задачи мы должны делать проверку на
наличие символа, стоящего перед окончанием ее , и только в
случае его отсутствия делать замену.
Давайте усложним задачу ещё несколькими условиями, чтобы
окончательно убедиться в «беспомощности» нашего решения:
— мы не знаем, в каком регистре написаны слова, например:
ее , Ее , ЕЕ ;

— также не знаем, используется ли буква ё .

В этом случае прямая замена уже точно «не подходит». Нам
нужна полноценная функция, которая проверит все условия.

«

«Не подходит» неслучайно взято в кавычки, ведь пока мы с
вами ничего не знаем о возможностях регулярных выражений
и не можем их применить в связке с .replace()

Где применять?
Как только появляется задача, в которой вы заранее не знаете
содержимое строки и не можете однозначно сформулировать
формат — с большой долей вероятности можно говорить о
необходимости использования регулярных выражений.
Обозначим основной круг задач, которые решают регулярные
выражения:
— Поиск или замена подстроки в строке с «плавающими»
(неизвестными) данными. Самая распространенная
задача — найти в тексте ссылки и адреса электронной
почты и сделать их кликабельными.
— Валидация данных формы и ограничение ввода.
Например, валидация номера телефона, электронной
почты, данных паспорта гражданина РФ и других данных.
— Получение части строки или формирование новых
структур данных из строк с «плавающими»

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

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

Основные термины
В контексте нашего курса мы будем использовать некоторые
термины, которые в других языках программирования и
технологиях могут иметь иное значение:
Строка — любой текст, включающий или не включающий в себя
символы перевода строки.
Подстрока — любая часть строки.
Паттерн, правило, шаблон, выражение — это часть или всё
регулярное выражение целиком. В русскоязычной среде
программисты также используют выражение «регулярка». В
англоязычных источниках могут встречаться сокращения RegEx
или RegExp , но это всё об одном и том же.
Селекторы — именно так будут в нашем курсе называться части
паттернов, из которых мы будем составлять регулярные
выражения.

Матчить текст — применить к строке правило регулярного
выражения с целью определения совпадения.

Мы только-только начинаем знакомиться с регулярными
выражениями, но уже написали первый паттерн. Далее
разберём, как работает поиск внутри самого выражения,
движения вперёд и возвраты.

1.2. Движение паттернов и возвраты
Мы обозначили круг задач, но ещё ни слова не сказали о
построении регулярных выражений (паттернов) и о том, как они
работают.
Давайте составим первый паттерн и попробуем найти

ее

средствами регулярных выражений:
/ее/.test('Быстрее всего мы догоним ее на машине'); // вернё

Первое, на что стоит обратить внимание из нашего примера: в
JavaScript регулярное выражение пишется между двух слэшей:
/{{селектор}}/ . Текст внутри выражения называют литералами,
а специальные символы, добавляющие функционал выражению
— метасимволами.
Второе, селектор может
предложением или строкой:

совпадать

с

целым

словом,

/Быстрее всего/.test('Быстрее всего мы догоним ее на машине'

«

Можно использовать регулярные выражения для поиска
подстроки в строке, но это не самое эффективное решение.
Мы поговорим об этом в следующих главах.

Здесь стоит остановиться и разобрать паттерн /ее/ , ведь это не
единое слово в его общем понимании, а набор из двух
символьных
селекторов,
следующих
в
определённой
последовательности.
Регулярное выражение, если намеренно не задан другой
порядок, будет последовательно перебирать символы строки
слева направо и искать первое совпадение с первым селектором
паттерна — е :

Когда будет найдено совпадение с первым селектором, не меняя
позиции и не возвращаясь к началу строки, механизм поиска
попробует сравнить следующий символ строки со следующим

селектором. Если и второй символ совпадёт, то на этом поиск
закончится.

Но что произойдет, если не будет совпадения? Механизму
придётся вернуться к первому селектору и продолжить искать
совпадение с позиции, на которой он в данный момент
находится.
Немного изменим строку поиска:
/ее/.test('Всего быстрее мы догоним ее на машине');

В нашем случае первое совпадение первого селектора е
произойдёт на слове всего . Затем механизм поиска перейдёт на

одну позицию вперед и попробует сопоставить второй селектор
е — а там буква г , которая не совпадает. Чтобы отбросить это
несовпадение и продолжить поиск дальше, придётся вернуться
на одну позицию назад и вернуться к первому селектору. Этот
механизм в регулярных выражениях называется возврат.
В зависимости от сложности текстовой строки и сложности
паттерна, возвраты могут происходить не только к селектору, но
и к начальной позиции строки. Чем больше (длиннее) само
регулярное выражение и чем чаще оно двигается назад, тем
больше сохраняет позиций в памяти. Поэтому большие и
сложные регулярные выражения — это всегда ресурсоёмкий код.
Важно научиться составлять паттерны так, чтобы был баланс
между точностью совпадения и скоростью обработки. При этом
вы всегда будете добиваться, чтобы регулярное выражение
совпадало с чем нужно и не совпадало со всем остальным. В
этом кроется эффективность написания регулярных выражений,
о которой мы будем говорить в течение всего курса.

Мы разобрали главный принцип движения и возвратов поиска
регулярного выражения в строке. От этого будет зависеть,
насколько эффективно мы будем писать выражения в
дальнейшем.

1.3. Атрибут pattern

Если

вы

верстаете

HTML,

то

наверняка

уже

успели

«попробовать» атрибут pattern в элементах форм или хотя бы
слышали о нем. Давайте освежим в памяти.

«

Для удобства чтения в этой главе мы заменим привычный
термин «паттерн» на слово «шаблон», чтобы понятия не
пересекались.

Итак,

атрибут

pattern="{{регулярное

выражение}}"

используется в HTML-элементах формы и .
Предназначен

pattern
для
проверки
корректности
(валидности) данных, вводимых в поле. Это единственный
атрибут, который требует отдельных знаний и навыков для
корректной настройки.

«

Важное замечание: pattern не является шаблонизатором
или ограничителем ввода. Он лишь управляет признаком
valid/invalid для вводимых данных.



Пример выше позволяет вводить в текстовое поле любое
количество не цифр. Если ввести данные, не подходящие под
условия pattern , отправка данных на сервер будет блокирована,
а поле выдаст подсказку:

Однако, как уже говорилось ранее, в строку всё ещё можно
ввести абсолютно любые символы.
С этим связывают проблему чрезмерной точности регулярного
выражения. Браузер не отображает значение pattern , поэтому
пользователь не знает, что разработчик заложил в шаблон
проверки. При попытке отправить неверные данные браузер
выведет «Пожалуйста, используйте требуемый формат», но при
этом не покажет, что именно неправильно.
Поэтому при использовании pattern стоит придерживаться
максимально простых правил, подсказку для которых можно
описать с помощью атрибута placeholder .
Для примера давайте напишем шаблон проверки паспорта
гражданина РФ:
{
if (element.id !== '' && /^[^a-zA-Z]/.test(element.id)) {
alert(`Elements id="${element.id}" is wrong!`);
}
});

Наблюдательный студент заметит, что мы использовали символ
карет ^ дважды. Один раз внутри символьного класса, чтобы
обозначить отрицание, а второй раз как самостоятельный
символ, но об этом далее.

Необязательно, чтобы правило искало точное совпадение,
можно найти и то, чего быть не должно. В этом и фокус!

2.6. Границы текста
Напоследок стоит рассказать о двух метасимволах, которые
могут упростить построение регулярного выражения и
сократить количество возвратов:

— ^ — символ начала текста,
— $ — символ конца текста.

Важно

уточнить,

что

для

многострочных

текстов

эти

метасимволы будут обозначать именно начало и конец всего
текста, а не его отдельных строк.
Сразу несколько примеров:
/^2021/.test('2020 год был менее богат на киношные события в

Здесь символ начала текста ^ является якорем, без которого
дальнейшая проверка селекторов невозможна. Поэтому, даже
несмотря на то, что в тексте присутствует 2021, результатом
будет false .
'Работа была сдана 25.09.2020'.replace(/[0-9]$/, '1') // Раб

В этом примере мы наоборот привязались к концу текста, хотя
совпадений с символьным селектором [0-9] предостаточно.
Решим реальную задачу
У нас есть массив с номерами мобильных телефонов клиентов, и
нам нужно передать их в API оператора для рассылки СМСсообщений. Но некоторые номера написаны с неправильным
кодом страны, 8 вместо 7 , и сообщения по этим номерам не
отправятся. Нужно исправить эту неточность.

const data = ['85558345434', '71236452378', '75558755555', '
const result = data.map(item => item.replace(/^8/, '7'))

В этом примере важно наличие знака начала строки ^ , ведь без
него будет заменён первый символ 8 в любом из номеров
телефонов, даже в правильных.

Подытожим. В регулярных выражениях языка JavaScript
многострочный текст считается единой строкой. У текста есть
границы, и пусть они невидимы, мы можем их обозначить и
построить выражение от них.

2.7. Рисуем смайлы
Нам с сервера приходит небольшой массив с комментариями
пользователей, в которых они добавляют длинные смайлы и тем
самым растягивают нашу вёрстку. Давайте исправим ситуацию и
вместо :) или :))))))))))))))))) поставим смайлик.

«

Для решения вам понадобится квантификатор + , он задаёт
повторения любого селектора. Также после выражения стоит

поставить

модификатор

срабатывало несколько раз.

const comments = [

/выражение/g ,

чтобы

правило

{
name: `Вера`,
comment: `Фильм укатайка :)))))))))))))))))))`
},
{
name: `Даниил`,
comment: `Были смешные моменты :), но в целом такое...`
},
{
name: `DarkLord`,
comment: `:)))))))))))))))))))))))))))))))))))))))))))))
}
];
comments.forEach((item, i) => {
// ваше решение
});
console.log(comments);

2.8. Рисуем смайлы (решение)
const comments = [
{
name: `Вера`,
comment: `Фильм укатайка :)))))))))))))))))))`
},
{
name: `Даниил`,
comment: `Были смешные моменты :), но в целом такое...`
},
{

name: `DarkLord`,
comment: `:)))))))))))))))))))))))))))))))))))))))))))))
}
];
comments.forEach((item, i) => {
item.comment = item.comment.replace(/:\)+/g, '😀');
});
console.log(comments);

Выражение /:\)+/ захватит первый селектор : и следующие
за ним последовательности из одной или нескольких скобок
\)+ .
Подумайте, как улучшить пример и вместо одного смайла
добавлять сразу три, если скобок больше 10.

3. Символьные селекторы
В этом разделе мы познакомимся с разнообразием символьных
селекторов, а также разберем нюансы их применения.

3.1. Символьные селекторы
Мы уже попробовали сделать первые шаги, но неужели всё
настолько сложно, разве нельзя как-то упростить регулярные
выражения?
Можно! И в этом нам помогут символьные селекторы.
Смысл символьных селекторов довольно простой: сократить
запись одиночных селекторов и их диапазонов. Условно можно
разделить все эти селекторы на смысловые и служебные.
Большинство этих селекторов имеют свои противоположные
значения, которые в регулярных выражениях называются
отрицаниями.
Мы будем изучать их сразу парами, чтобы было легче запомнить.
\d — все цифры, \D — все не цифры.
Символьному селектору \d будет соответствовать диапазон
[0-9] , а

соответственно

[^0-9] . В своих регулярных
выражениях вы можете использовать любые селекторы и их
комбинации, так как они равнозначны в использовании.

\D

Совпадает селектор \d , как и одиночный символ или диапазон,
только с одним символом в тексте.
Для сокращения выражения символьный селектор может быть
записан в квадратные скобки [\d] , но такая запись не устоялась,
и обычно его используют отдельно.
JS .

Если эти сокращения написаны строчными — заменить на
прописные. Важно, чтобы выражение не совпадало на
расширениях файлов.

const str = `Одностраничное приложение — это приложение, кот
const Abbr = {
CSS: `Cascading Style Sheets`,
HTML: `Hyper Text Markup Language`,
JS: `JavaScript”`
};
const insertAbbr = (str) => {
// ваш вариант решения
};

insertAbbr(str);

4.6. Торжество лени (решение)
const str = `Одностраничное приложение — это приложение, кот
const Abbr = {
CSS: `Cascading Style Sheets`,
HTML: `Hyper Text Markup Language`,
JS: `JavaScript`
};
const insertAbbr = (str) => {
if (!str) {
return ``;
}
const regex = new RegExp(`(\\.)?\\b(${Object.keys(Abbr).jo
return str.replace(regex, (string, $1, $2) => {
if (!$1) {
const upper = $2.toUpperCase();
return `${upper}`;
}
return $1 + $2;
});
};
insertAbbr(str);

Для решения задачи

мы

использовали

конструктор

new

RegExp() , внутри которого собрали значения ключей исходного
объекта в разных регистрах.
Обращаем внимание, что в случае с конструктором регулярное
выражение записывается как строковое значение, где символ
обратного слэша \ должен быть экранирован \\ .
Разберем само выражение:
— Скобки (\\.)? сохранят точку если в тексте попадется
выражение типа index.html, она нужна нам чтобы отсечь
подобные совпадения в будущем
— Выражение
\\b(${Object.keys(Abbr).join('|')}|${Object.keys(Abbr
).map((abbr) => abbr.toLowerCase()).join('|')})\\b
соберет все возможные варианты совпадения ключей в
нижнем и верхнем регистре. После компиляции оно
будет выглядеть так \b(CSS|HTML|JS|css|html|js)\b .
Обязательно устанавливаем границы слов \b , чтобы в
выборку не попадали посторонние конструкции,
например jsDoc
— Далее, уже в самой функции замены, проверяем
отсутствие точки перед аббревиатурой, переводим
совпадение в верхний регистр и выводим тег

4.7. Тест по пройденному материалу
Повторим основные моменты, которые были рассмотрены во 2—
4 разделах.

. Регулярные выражения чувствительны к регистру?
— Нет
— Да

. Как выглядит набор букв для селектора
переписать его в квадратных скобках?

\w , если

— [a-z0-9_]
— [a-zA-Z0-9_]
— [a-zA-Zа-яА-Я0-9_]

. Как правильно записать «не число»?
— \D
— ^[0-9]
— [^0-9]

. С чем совпадёт \d\.\d ?
— С целым числом.
— С числами, между которыми стоит любой символ, кроме
\n .
— С дробным числом.

. Какое выражение будет верно для даты 24.11.2021?
— \d{1,2}.\d{1,2}.\d{4}
— \D{1,2}\.\D{1,2}\.\D{4}
— \d{1,2}\.\d{1,2}\.\d{4}

. Что сделает следующее выражение? (?:[a-z]|\d)

— Совпадёт с латинской буквой, перед которой есть вопрос
и двоеточие, или цифрой, при этом совпадение
сохранится.
— Совпадёт с латинской буквой или цифрой, при этом
совпадение не сохранится.
— Совпадёт с латинской буквой или цифрой, при этом
совпадение сохранится.

4.7. Тест по пройденному материалу (ответы)
. Регулярные выражения чувствительны к регистру?
— Да

. Как выглядит набор букв для селектора
переписать его в квадратных скобках?

\w , если

— [a-zA-Z0-9_]

. Как правильно записать «не число»?
— \D
— [^0-9]

. С чем совпадёт \d\.\d ?
— С дробным числом.

. Какое выражение будет верно для даты 24.11.2021?
— \d{1,2}\.\d{1,2}\.\d{4}

. Что сделает следующее выражение? (?:[a-z]|\d)
— Совпадёт с латинской буквой или цифрой, при этом
совпадение не сохранится.

5. Квантификаторы. Ограничения
длины. Жадность
В этом разделе мы познакомимся с численными ограничениями,
научимся решать задачи с неизвестным и неограниченным
числом совпадений.

5.1. Что если не?
Мы уже познакомились с численными квантификаторами и
можем ограничить длину выражения. Но что делать, если
заранее не знаем, есть ли в тексте заданная конструкция или
нет? Если что-то может появляться и пропадать, но при этом
совпадения от этого не страдают? На этот случай есть
специальный квантификатор ? , который применяется как к
отдельным селекторам, так и группам селекторов, заключенным
в квадратные []? или круглые ()? скобки.
У квантификатора ? есть эквивалент в виде фигурных скобок
{0,1} , то есть совпадение может быть, а может не быть.
Аналог условия if без альтернативного else .
Например,

когда

вы

просите

записать

кого-то

номер

мобильного, то диктуете, начиная с 7 или 8 . А кто-то перед
этим проговаривает + или, наоборот, начинает со второй
цифры. Но в целом мы всегда понимаем, о чём речь, и номер от
этого не становится менее правильным.

Давайте запишем это в виде паттерна:
{
if (!str || !chars) {
return str;
}
const regex = new RegExp(`^[${chars}]*([\\s\\S]+?)[${chars

return str.replace(regex, '$1');
};
trimChars(`*-text\ntext*-*-*`, `*-`);

«

Обращаем внимание, хоть пример вызова функции и написан
одной строкой, он содержит перевод строки \n и является
многострочным.

В решении интересна конструкция [\s\S]+ , которую можно
описать так: все пробельные и непробельные символы. Она
захватит в силу «жадности» всё между символами, переданными
в параметре chars .
Для решения мы применяем конструктор, так как нам нужно
добавлять значения символов внутрь регулярного выражения из
переменной.

Быть «жадным» не так уж и плохо. Главное, не увлекаться и
понимать, как это можно использовать.

5.3. Ни одного или много *
Ещё один жадный квантификатор, сочетающий в себе мощь двух
первых — символ звёздочка * . Эквивалент фигурных скобок

{0,} , он означает ни одного или бесконечное множество
совпадений.
Применяется как к отдельным литералам или селекторам, так и
группам селекторов, заключенным в квадратные

[]*

или

круглые ()* скобки.
Так же как и ? , даёт возможность не включать части совпадений
и, с другой стороны, если совпадение состоялось — захватывать
всё. Поэтому .* эквивалентна .+ и захватит всю строку, кроме
символа перевода строки \n .
Очень часто звездочку используют вместе с селектором
пробельных символов \s , потому что заранее никогда не
известно, какие пробельные символы используются в тексте и
есть ли они вообще.
Решим реальную задачу
Привяжем все знаки №
неразрывным пробелом.

в тексте к последующим цифрам

const str = `Постановления Правительства от 30.12.2019 №1717
str.replace(/№\s*(\d+)/g, '№ $1'); // Постановления Пра

Разберем прошлый пример
Мы писали шаблон проверки паспорта гражданина РФ:

. То есть «жадность» будет работать в
ограниченном диапазоне.

«

Подумайте, что выберет регулярное выражение .+?$

Продолжим задачу про теги. Теперь мы можем ограничить
жадность и получить правило для удаления тегов из строки —
, где якорем будет первая закрывающая угловая
скобка.
const str = `Title {
return str ? str.replace(//g, ' ').trim().re
};
removeTags(str);

Внимательный студент заметит, что в методе .replace() мы
используем пробел, а не пустую строку для удаления тегов. Это

нужно для того, чтобы текст, написанный в блочных тегах, не
слипался в единую строку без пробелов.
Решим реальную задачу
Напишем функцию, возвращающую значение, которое будет
совпадать со строкой справа от якоря, заданного регулярным
выражением.
const rightMatch = (str, anchor) => {
if (!str || !anchor) {
return str;
}
const regex = new RegExp(`^.*?${anchor}(.*?)$`);
return str.replace(regex, (source, $1) => $1 ? $1 : source
};
rightMatch(`12:01, 14:05, 18:00, 21:20 Спортивные новости`,

Важно: при использовании функции необходимо экранировать
обратные слэши в описании якоря по правилам JavaScript.

Мы изучили разнообразие квантификаторов и ограничение
длины совпадений, понятия «жадный/ленивый» квантификатор и
ограничение «жадности».

5.6. Опишем уровень игры
Мы решили запрограммировать маленькую игру и нарисовать
карту уровня в виде спрайтов. Чтобы карта загружалась и
отрисовывалась корректно, мы связали буквы латинского
алфавита со спрайтами. Например, A — это стены, b — трава, D
— дверь, X — сундук с кладом.
const level = [
`AAAAAAAAAA`,
`AbbbbbbbbA`,
`DbbbbXbbbA`,
`AbbbbbbbbA`,
`AAAAAAAAAA`
];

Но в таком виде карты получаются большими, и мы решили
немного сократить место, применив простой алгоритм сжатия.
Для этого нам нужно записать первую латинскую букву и рядом
цифру, соответствующую количеству повторений.
В итоге у нас должен получиться такой массив:
const level = [
`A10`,
`A1b8A1`,
`D1b4X1b3A1`,
`A1b8A1`,
`A10`
];

Чтобы зашифровать его, нам нужна функция, которая на вход
примет исходную строку AAAAAbbbbbbDbbb , а на выходе вернёт
сжатую A5b6D1b3 :
const compress = (str) => {
// ваше решение с помощью регулярных выражений
};

5.7. Опишем уровень игры (решение)
const compress = (str) => {
if (!str) {
return ``;
}
const parts = str.match(/([a-zA-Z])(\1)*/g);
let result = '';
parts.forEach((item) => {
result += item[0] + item.length;
});
return result;
};

5.8. Тест по разделу квантификаторы

Повторим основные моменты, которые были рассмотрены в
разделе.
. Какой квантификатор можно по-другому записать как
{0,1}?
— Звездочка *
— Плюс +
— Вопрос ?
. Результатом какого выражения будет массив [‘r’]?
— Вариант 1
const parts = 'regular expression'.match(/[a-z]*?/)

— Вариант 2
const parts = 'regular expression'.match(/[a-z]+?/)

. С чем совпадет .+?$ в выражении?
const parts = 'regular expression'.match(/.+?$/);
— С последней буквой `n`.
— С последним словом `expression`.
— Со всей фразой `regular expression`.

. С чем совпадет (.+?)* в слове `regular`?

— Ни с чем.
— Со всем словом.
— С первой буквой.

5.8. Тест по разделу квантификаторы
(ответы)
. Какой квантификатор можно по-другому записать как
{0,1}?
— Вопрос ?

. Результатом какого выражения будет массив [‘r’]?
— Вариант 2
const parts = 'regular expression'.match(/[a-z]+?/)

. С чем совпадет .+?$ в выражении?
const parts = 'regular expression'.match(/.+?$/);
— Со всей фразой regular expression .

. С чем совпадет (.+?)* в слове regular ?
— Со всем словом.

6. Опережающие и
ретроспективные проверки.
Модификаторы
В этом разделе мы познакомимся с условиями, которые
позволяют регулярным выражениям заглядывать вперед и назад,
а также познакомимся с модификаторами.

6.1. Позиционные проверки
Чтобы понять позиционные проверки, нужно вспомнить, как
ведут себя символы начала и конца строки. Это не отдельный
литерал — это позиция в тексте. С позиционными проверками
ситуация похожая, это не нахождение и сохранение
захваченного текста, а нахождение позиции в тексте, при
которой может возникнуть совпадение.

«

Стоит отметить, что скобки позиционных проверок не
являются сохраняющими и не получают номера сохранения.

Позиционные проверки могут быть опережающими и
ретроспективными, то есть заглядывать относительно позиции
вперед или назад. Каждая сама по себе может быть позитивной
или негативной, что говорит о совпадениях или несовпадениях.
Все доступные варианты позиционных проверок описаны в
таблице:

Проверка

Описание

x , справа от

x(?=y)

опережающая проверка (найдет
которого есть y )

x(?!y)

негативная опережающая проверка (найдет
справа от которого нет y )

(? /^(\d{1,3}(\.|$)){4}$/.test(ip);

Давайте усложним пример: добавим проверку, что значения
чисел не могут быть больше 255.
const checkIP = (ip) => /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\
checkIP(`234.56.38.3`); // true
checkIP(`255.255.255.255`); // true
checkIP(`192.168.1.1`); // true

Почему наш первый пример был не настолько хорош? Кроме
того, что он допускал числа большие 255 , он бы сработал на
адресе, у которого в конце имеется точка 127.0.0.1. . В новом
варианте мы исключили такую возможность, так как проверили
наличие конца строки с помощью опережающей негативной
проверки \.(?!$) . В позиции перед точкой нет символа конца
строки.
Поддержка браузерами

Большинство современных браузеров уже поддерживает
ретроспективные проверки в регулярных выражениях, но до
сегодняшнего момента их не поддерживает Safari. Прежде чем
применять их в своих проектах, подумайте, на какую аудиторию
вы рассчитываете и сверьтесь с таблицей поддержки.

Заглядывать в будущее и прошлое не так уж и сложно. Магия
всегда была рядом, мы просто не умели её применять.

6.2. Модификаторы
Мы смотрели разные примеры и лишь вскользь касались
модификаторов. Пришло время разобрать, что это и зачем их
использовать.
Модификаторы (флаги) используют для упрощения регулярных
выражений и изменения поведения некоторых селекторов.
Список основных модификаторов
Модификатор

Описание

g

искать все совпадения

i

не учитывать регистр

m

многострочный режим

Модификаторы записывают двумя способами:

— в литеральном виде сразу после ограничивающего слэша
/выражение/модификатор ;
— в случае с конструктором — в виде отдельного параметра
new RegExp('выражение', 'модификатор') .

Модификаторы можно использовать как по отдельности, так и
составляя различные комбинации. Порядок их следования
значения не имеет.

Модификатор g
const str = `Булочка`;
/[а-яёА-ЯЁ]/g.test(str); // true

Как мы помним из начала курса, квадратные скобки без
квантификатора + или * дают нам совпадение только с одним
символом, но модификатор g меняет это поведение. В нашем
примере выражение возвращает true для первого символа.
Потом, не меняя позицию, за счёт флага

g регулярное
выражение будет пытаться совпасть снова уже со вторым
символом и тоже вернет true — и так до конца. В итоге всё
слово окажется совпавшим.
Гораздо интереснее модификатор g работает с точкой . .

«

Из

предыдущего

раздела:

точка

совпадает

символами, кроме перевода строки \n .

со

всеми

const str = `один
два
три`;
str.match(/.+/); // ['один']
str.match(/.+/g); // ['один', 'два', 'три']

Что здесь важно, в первом случае без модификатора «жадный»
квантификатор .+ захватит только первую строку, потому что
\n является символом несовпадения.
В случае с модификатором g он также захватит только первую
строку. Но так как перевод строки не является символом, это
всего лишь позиция в тексте, то модификатор продолжит
захватывать дальше с этой позиции. Тем самым захватит весь
текст, но в нём не будет переводов строк.
Прочувствовать эту разницу можно на следующем примере:
заменим .+ на другое выражение [\s\S]+ .

«

Селектор \s включает в себя все пробельные символы, в том

числе и перевод строки, а \S всё, кроме пробельных
символов.

const str = `один
два
три`;
str.match(/[\s\S]+/); // ['один\nдва\nтри']

Как мы видим, здесь модификатор не нужен, так как с первого
раза захвачена вся строка.
Важно

понимать

разницу

поведения

селектора

.

в

совокупности с модификатором g , чтобы случайно не удалить
переводы строк.

Модификатор i
Ещё один интереснейший модификатор — i . Он позволяет
выражению становиться нечувствительным к регистру.
Оптимизируем одну из задач
В предыдущем разделе мы уже оптимизировали правило
проверки наличия шестнадцатеричного цвета в строке:
/#[0-9A-Fa-f]{6}/.test('Этот цвет #FF0000 — красный');
Использование модификатора позволит нам ещё раз сократить
регулярное выражение:
/#[0-9a-f]{6}/i.test('Этот цвет #FF0000 — красный');
Достаточно написать любую последовательность латинского
или русского алфавита в любом регистре, остальные варианты
правило подставит само.

Модификатор m

Ещё

один

модификатор,

селекторов —

который

влияет

на

поведение

m . Он позволяет регулярному выражению

воспринимать текст как многострочный, где символы начала ^ и
конца $ текста будут восприниматься как начало и конец
строки.
const str = `один
два
три`;
str.match(/^[а-я]+?\n/); // ['один']

Чтобы захватить только первую строку, нужно описать её
содержимое, включая перевод строки.
const str = `один
два
три`;
str.match(/^[а-я]+?$/m); // ['один']

В случае с модификатором нам достаточно обозначить конец
строки $ , и он станет якорем для «жадного» квантификатора.

Магия регулярных выражений заключается в умении
комбинировать различные селекторы и модификаторы для
достижения наилучшего эффекта.

6.3. Триадам да
Дизайнер просит, чтобы все числа в тексте были разбиты на
триады и переносились на новую строку только целиком.
Давайте поможем ему познать дзен.
const text = `В больших городах медианная зарплата ИТ-специа
const parseTriads = (str) => {
// ваше решение
};
parseTriads(text);

6.4. Триадам да (решение)
const text = `В больших городах медианная зарплата ИТспециалиста в 2018 году составляла 92000 рублей. Зарплата
начинающего специалиста — 46000 рублей. Медианная зарплата
того же специалиста в иностранных компаниях составляла
220000 рублей.`;
const
parseTriads
=
(str)
=>
str
?
str.replace(/(\d{5,})/g, (text, $1) => $1.replace(/(? /^[a-z0-9_.-]+@[a-z0-9-]+\.[a-

Давайте проговорим правило:
— ^[a-z0-9_.-]+ — это имя, где от начала строки
встречаются латинские буквы, цифры и некоторые знаки;
— затем символ @ или в простонародье «собака»;
— дальше идёт доменная часть, которая разбита на
доменное имя [a-z0-9-]+ и доменную зону [a-z0-9-.]+ .

С одной стороны, это необходимый минимум для валидации. Но
всегда найдутся перфекционисты, которые скажут, что правило
не покрывает абсолютно все варианты адресов по стандарту
RFC.
Вот

пример

корректного

адреса

электронной

почты

!#$%&'*+-/=?^_{}|~@example.com
Готовы ли вы в своих проектах поддерживать подобное —
решать вам. Стоит лишь помнить, что любое усложнение правил
создаёт дополнительные варианты возвратов, и, как следствие,
потерю в скорости работы скрипта и излишний расход памяти.
Неплохой обзор проблемы можно прочитать в статье «Никогда
не проверяйте e-mail адреса по стандартам RFC».
Мы же, со своей стороны, обязаны показать вам, как проверить
адрес по стандарту RFC 5322:

const checkEmail = (email) => /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-

Так выглядит боль.
самостоятельно 🤪

Попробуйте

проговорить

правило

Кроме боли должно быть что-то необычное, и вот вам
экзотический вариант:
const checkEmail = (email) => {
let input = document.createElement(`INPUT`);
input.type = `email`
input.value = email;
return input.checkValidity();
};

Вам может показаться, что здесь нет регулярных выражений, и
это правда. В коде явно нет. Но вы запрашиваете валидацию
через поле формы, которое по умолчанию обращается к
регулярному выражению в самом браузере.

Точность — не всегда хорошо. Если вы не валидируете счёт, на
который вам поступает зарплата, то смело можно писать более
простые правила. Перфекционизм — всегда затратно.

7.3. Скорость выполнения

Последний пример из предыдущей главы подвёл нас к ещё
одному важному вопросу, который входит в понятие
эффективности — скорость выполнения.

«

Нужно ли использовать регулярное выражение везде при
работе с текстом?

— Нет, не нужно!
Хотя наш курс называется «Регулярные выражения» и мы
должны их хвалить, но всегда следует подходить к решению с
холодной головой и обязательно тестировать, сравнивая с
другими вариантами решения.
Для примера возьмём одну из уже знакомых нам функций,
возвращающую
правую
часть
строки,
и
замерим
производительность:
const COUNT = 10000;
const rightMatch = (str, anchor) => {
if (!str || !anchor) {
return str;
}
const regex = new RegExp(`^.*?${anchor}(.*?)$`);
return str.replace(regex, (source, $1) => $1 ? $1 : source
};

let time = performance.now();
for (let i = 0; i < COUNT; i++) {
rightMatch(`12:01, 14:05, 18:00, 21:20 | Спортивные новос
}
time = performance.now() - time;
console.log('Время выполнения = ', time); // 18 миллисекунд

А теперь напишем ту же функцию, только стандартными
методами JavaScript:
const COUNT = 10000;
const rightMatch = (str, anchor) => {
if (!str || !anchor) {
return str;
}
return str.substr(str.indexOf(anchor) + anchor.length);
};

let time = performance.now();
for (let i = 0; i < COUNT; i++) {
rightMatch(`12:01, 14:05, 18:00, 21:20 | Спортивные новос
}
time = performance.now() - time;

console.log('Время выполнения = ', time); // 4.2 миллисекунд

Мы

производили

измерения

на

одинаковом

количестве

повторений в цикле 10000 двумя разными способами:
— с помощью регулярного выражения,
— с помощью методов работы с подстрокой.

Результат
получился
закономерным:
18
против
4.2
миллисекунды. Это доказывает, что регулярные выражения
работают медленнее нативных методов.
Стоит отметить, что на разных компьютерах и операционных
системах результат выполнения примеров будет отличаться, но
тренд в разности скорости сохранится.

«

Так почему же стоит использовать регулярные выражения?

Для упрощения примера мы намеренно изменили исходную
строку 12:01, 14:05, 18:00, 21:20 | Спортивные новости .
Добавили туда якорный символ | , чтобы было легче написать
ответную нативную функцию.
А теперь представьте, что будет, если убрать якорь | и как в
изначальном примере искать по последнему времени, точного
значения которого мы не знаем?
12:01, 14:05, 18:00, 21:20 Спортивные новости

Вы можете парировать, что можно искать по цифре, а если так?
12:01, 14:05, 18:00, 21:20 26 Бакинских комиссаров
Каждое подобное изменение будет обходиться вам дорого с
точки зрения затраченного времени на написание функции. К
тому же не так много задач, которые требуют перебора
настолько большого объема строк.

Выбор технологии и алгоритма решения — это всегда баланс
нескольких факторов. Регулярные выражения — всего лишь
инструмент.

7.4. Каскады правил
Мы рассмотрели сложный пример регулярного выражения
проверки адреса электронной почты. В этом примере мы были
вынуждены
составить очень сложную и
громоздкую
конструкцию. Но это скорее исключение из правил.
Во многих задачах можно разбить одно большое правило на
каскад (несколько) маленьких. Они в сумме будут давать тот же
результат, но при этом станут расходовать меньше памяти и
будут эффективнее по скорости выполнения.
Каждое

правило

каскада

получает

результат

работы

предыдущего, обрабатывает и передаёт дальше, пока не будут
выполнены все правила.

Мы с вами уже решали похожую задачу с расстановкой абзацных
тегов:
const setParagraph = (str) => (str) ? `${str.replace(/\n{

Здесь

используется

каскад

из

двух

правил.

Сперва

захватываются два и более подряд переводов строк \n и
заменяются на . Затем, после первой замены, результат
передаётся следующему правилу, которое заменяет оставшиеся
одиночные переводы строки на .
При написании каскадов, как и в примере выше, важен порядок
следования. Если мы поменяем правила местами, то получим
совсем другой результат.
const setParagraph = (str) => (str) ? `${str.replace(/\n/

Все переводы строк заменятся на , а двойные и более
переводы строк не совпадут ни с чем.
Можно написать более универсальное
построчно обернёт абзацы:

правило,

которое

const setParagraph = (str) => (str) ? str.replace(/^(.*?)$/g

У данного решения есть две проблемы:

— не решён вопрос с одиночными переводами строк,
— скобки будут сохранять текст в памяти прежде чем
оборачивать тегами, и это может быть очень
ресурсоемкой операцией, особенно на больших объемах
текста.
Чтобы правило заработало корректно, придётся усложнить его.
В итоге мы можем получить нечто похожее на правило
валидации электронной почты.
Не пытайтесь разложить всю задачу в одном регулярном
выражении, это может оказаться неэффективно.
Типограф
Ярким примером «каскада» (да и в целом задачи, основанной на
регулярных выражениях) можно назвать «Типограф».

«

Типограф — это средство онлайн подготовки текста к вебизданию. Он помогает избежать монотонной корректировки,
расстановки кавычек, неразрывных пробелов, специальных
символов, исправляет некоторые ошибки ввода (опечатки) и
выполняет другие задачи. В его основе собрано около 200
правил экранной типографики и книжной вёрстки.

Если вы раньше не сталкивались с этим сервисом, вот
небольшой пример его работы:
Исходный текст:

...Когда В. И. Пупкин увидел в газете ( это была "Сермяжная
правда" №

45) рубрику Weather Forecast(r), он не поверил

своим глазам - температуру обещали +-451F.
Результат обработки в виде кода:
&hellip;Когда
в&nbsp;газете

В.

(это

&#8470;&nbsp;45)

была

И.

&laquo;Сермяжная

рубрику Weather

,
глазам&nbsp;&mdash;

Пупкин

правда&raquo;

Forecast&reg;

он&nbsp;не&nbsp;поверил
температуру

увидел

обещали

своим

&plusmn;451

&deg;F.
Результат обработки в виде текста:
…Когда В. И. Пупкин увидел в газете (это была «Сермяжная
правда» № 45) рубрику Weather Forecast®, он не поверил своим
глазам — температуру обещали ±451 °F.
Вот что сделал Типограф:
— расставил абзацные теги;
— заменил три отдельные точки на символ многоточия;
— связал в неразрывную конструкцию инициалы и
фамилию, чтобы они переносились на новую строку
целиком;
— привязал союзы и предлоги, чтобы они всегда
переносились на новую строку со следующим словом;
— удалил пробелы внутри скобок;

— заменил кавычки в виде классических " дюймов на
принятые в русском «ёлочки»;
— привязал символ № к числу неразрывным пробелом;
— заменил (r) на символ зарегистрированного товарного
знака (r) , сделал его меньше основного кегля и
выровнял по верхней границе;
— заменил дефис - на длинное тире — и привязал его к
предыдущему слову;
— заменил знак «плюс-минус» +-451F на ±451 °F и связал в
неразрывную конструкцию.

Если вы верстаете регулярно, то понимаете, насколько трудно
бывает вручную отлавливать и исправлять все эти моменты.
Мы хотим вам помочь, пользуйтесь: https://typograf.ru

Что мы должны вынести из темы оптимизации: истина находится
где-то посередине. Не существует единого и универсального
рецепта, который решит все ваши проблемы. Полагаться стоит
только на полученный опыт и тестирование.

7.5. Регулярные выражения в среде
окружения
Мы изучили основную теоретическую часть регулярных
выражений, осталось добавить несколько практических
примеров использования.

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

выражений

есть

в

большинстве

— MS Word,
— LibreOffice,
— NeoOffice,
— Atom,
— Visual Studio Code (VS Code),
— Sublime,
— WebStorm
— и многих других…

Искать регулярные выражения нужно в интерфейсе поиска и
замены, а выглядит это примерно так:
VS Code

Atom

NeoOffice

При зажигании соответствующего флага ваша строка начинает
восприниматься как регулярное выражение, и дальше вы можете
применять полученные в ходе курса знания.
Стоит отметить, что большинство из того, что мы изучали,
справедливо в редакторах, но могут быть и особенности.

Поэтому обязательно ознакомьтесь с таблицей поддерживаемых
селекторов того редактора, с которым работаете.
Часто бывает так, что некоторые символьные селекторы
работают не так, как в JavaScript.
Например, \w может совпадать с русскими буквами или может
не включать в себя цифры и символ подчеркивания. Но мы же с
вами уже знаем, что любой символьный селектор можно
заменить квадратными скобками с набором символов, поэтому
это не должно стать проблемой.
Какие задачи можно решать с помощью регулярных выражений
в текстовых редакторах? Вот основной перечень задач:
— поиск и гибкая замена с сохранением состояния
текста,
— подготовка, обработка данных,
— написание кода.
Давайте пройдём по этим задачам и посмотрим, как можно
упростить себе жизнь.
Поиск и замена
В процессесоздания этого курса выяснилось, что разметка
MarkDown, с помощью которой написаны статьи, конфликтует с
частями регулярного выражения и заменяет их. Чтобы
избавиться от проблемы, нужно было обернуть регулярные
выражения в бэктики.

Делать это вручную весьма скучно, долго, да и можно что-то
упустить. Поэтому самое время заставить компьютер работать за
нас.

Посмотрите внимательно на скриншот. В синем круге обведены
регулярное выражение \*\*(.+?)\*\* и выражение замены со
вставкой сохранённого состояния круглых скобок $1 .
Для уточнения мы могли бы добавить выражение начала строки.
Но как видно на скриншоте (обведено зеленым), оно и так
совпало с тем, что мы ожидали.

«

Только задумайтесь, мы написали регулярное выражение,
чтобы исправить ошибку регулярного выражения MarkDownразметки в статье про регулярные выражения 🤪

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

Подготовка, обработка данных
Вспомните, в одном из разделов мы решали задачу по
подготовке номеров мобильных телефонов для отправки СМС.
Эта задача возникла из практического примера, где помимо
неверно записанных номеров попадались ещё и пропущенные
строки, короткие записи городских номеров, невалидные 12-ти
значные номера. Файл имел размер в несколько мегабайтов, и
приводить его в порядок вручную было бы непросто.

Решить задачу «в лоб», как в первом случае, здесь не получится.
У нас совершенно разные маленькие задачи, и здесь нам
понадобится «каскад» правил с одной лишь разницей:
записывать и применять их будем поочерёдно.

Первое, что мы сделаем — избавимся от пустых строк. Для этого
напишем простое правило ^\n и заменим на ничего.

Затем удалим все номера длиннее 11 знаков с помощью правила
^\d{12,}\n . Здесь важно включать селектор начала строки ^
как якорь и перевода строки
оставалось пустых строк.

\n , чтобы при замене не

Следующим шагом удалим все городские номера короче 11
знаков с помощью правила ^\d{1,10}\n .

И теперь заменим все восьмёрки в начале строки на семёрки,
потому что правильный код страны России — 7 .

«

Все совпадения номеров мобильных телефонов в примере с
действующими номерами случайны!

В результате за пару минут с помощью практического
применения регулярных выражений мы подготовили большой
файл с данными.
Написание кода
При разработке часто приходится писать похожие конструкции,
у которых изменяемая часть хотя и незначительна, но требует
большого количества копипасты и внимательной доводки
руками.

const renderCard = ({title, timeIn, timeOut, type, guests, r
const newCardElement = document.cloneNode(true);

// выбрать все элементы внутри склонированной ноды с соо
};

«

Пример взят из курса «JavaScript. Профессиональная
разработка веб-интерфейсов», проект «Кексобукинг».

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

«

Маленький лайфхак: иногда строить регулярное выражение
для фрагмента текста очень сложно. Оно постоянно

совпадает с чем-то лишним, а нужно, чтобы оно сработало в
ограниченной части строки. На помощь приходит флаг
«найти в выделенной области». Он тоже присутствует во
многих редакторах. Выделите текст и применяйте регулярное
выражение только внутри выделения.
Так мы и поступим. Вставим параметры, добавим лишнюю
запятую в конце, чтобы не усложнять выражение, и заменим
сохранённые

скобки

(\w+)

\tnewCardElement.querySelector('.card-$1').textContent

на
=

$1;\n .
Обращаем внимание, что спереди мы поставили символ
табуляции \t , а сзади — перевод строки \n , чтобы не только
вставить код, но и сразу отформатировать его.

Пример может показаться очень синтетическим, но он хорошо
отражает суть. Достаточно часто в практике приходится
переписывать поля из одной структуры в другую, и от этой
рутины всегда можно избавиться.
Где ещё встречаются?
Сейчас регулярные выражения интегрированы практически во
все средства разработки, а также:
— в языки программирования,
— в базы данных,
— в системные утилиты,
— в настройки серверов
— и много куда ещё…
Некоторые языки программирования и программные продукты
не полностью поддерживают список селекторов или, наоборот,
поддерживают гораздо больше, чем мы изучили.

«

К слову, поддержка регулярных выражений в языке JavaScript
не самая широкая.

Везде есть свои нюансы использования регулярных выражений,
но в целом знания, полученные на курсе, позволят вам с
легкостью адаптироваться к любым новым условиям.
Напоследок, чтобы вы больше практиковались в регулярных
выражениях, рекомендуем пару удобных онлайн сервисов:

— https://regex101.com/
— https://regexr.com/

Регулярные выражения получили своё практическое признание
в огромном количестве программных продуктов. Надеемся, что и
вы им найдёте достойное применение!

7.6. Финальный тест по программе курса
Повторим основные моменты, которые были рассмотрены на
курсе.
. С каким типом данных работает регулярное выражение?
— Любым.
— Числами, строками, датами.
— Только со строками.

. Какова основная задача, решаемая с помощью регулярных
выражений?
— Поиск подстроки в строке с «плавающими» данными.
— Валидация данных формы и ограничение ввода.

. С чем совпадёт [а-яa-z]?
— С любой буквой.
— С любыми буквами в нижнем регистре.
— С буквой русского и английского алфавита в нижнем
регистре.

. Включает ли символьный селектор `\w` цифры?
— Нет не включает.
— Да, включает вместе с символом `_`.
— Да, включает без символа `_`.
. С чем совпадёт паттерн: `\d+.\d+`?
— Дробные числа.
— Дробные числа, целые числа и числа, между которыми
стоит любой символ, кроме `\n`.
— Целые и дробные числа.
. Как правильно записать регулярное выражение `любое
целое число` через конструктор?
— `new RegExp(‘\d+’)`
— `new RegExp(‘\\d+’)`
— `new RegExp(‘\\d’, ‘g’)`
. Какое из отрицаний в паттерне говорит «совпасть с не
числом»?
— `\D`
— `[^0-9]`
— `\d?`
. Как записать квантификатор `*` с помощью численного
квантификатора?
— `x{1,}`
— `x{0,∞}`
— `x{0,}`

. В регулярном выражении `.*?` квантификатор `*` «жадный»
или «ленивый»?
— Жадный.
— Ленивый.
. Как называется проверка в выражении `\.(?!$)`?
— Опережающая позитивная.
— Ретроспективная позитивная.
— Опережающая негативная.
— Ретроспективная негативная.

7.6. Финальный тест по программе курса
(ответы)
. С каким типом данных работает регулярное выражение?
— Только со строками.
. Какова основная задача, решаемая с помощью регулярных
выражений?
— Поиск подстроки в строке с «плавающими» данными.
. С чем совпадёт [а-яa-z]?
— С буквой русского и английского алфавита в нижнем
регистре.
. Включает ли символьный селектор `\w` цифры?
— Да, включает вместе с символом `_`.
. С чем совпадёт паттерн: `\d+.\d+`?

— Дробные числа, целые числа и числа, между которыми
стоит любой символ, кроме `\n`.
. Как правильно записать регулярное выражение `любое
целое число` через конструктор?
— `new RegExp(‘\\d+’)`
— `new RegExp(‘\\d’, ‘g’)`
. Какое из отрицаний в паттерне говорит «совпасть с не
числом»?
— `\D`
— `[^0-9]`
. Как записать квантификатор `*` с помощью численного
квантификатора?
— `x{0,}`
. В регулярном выражении `.*?` квантификатор `*` «жадный»
или «ленивый»?
— Ленивый.
. Как называется проверка в выражении `\.(?!$)`?
— Опережающая негативная.