Полезные регулярные выражения
Пользовательские данные#
1. Юзернейм#
Стандартный формат юзернейма – цифры, строчные буквы, символы - и _. Разумная длина – от 3 до 16 знаков. В зависимости от ваших конкретных потребностей вы можете изменять набор символов (например, разрешить символ *) и длину строки.
/^[a-z0-9_-]{3,16}$/
JS:
re.test('normal_login-123'); // true
re.test('IncorrectLogin'); // false
re.test('inc*rrect_l*gin'); // false
Что используем: Символы ^ и $ указывают на начало и конец строки, так что введенный юзернейм будет проверен на совпадение полностью от первого до последнего символа.
2. Валидация email#
Проверка адреса электронной почты на корректность – одна из самых частых задач веб-разработчика. Без этого не обходятся ни разнообразные формы подписки, ни авторизация.
Для валидации email существует множество различных регулярок. Вот одна из них – не самая большая и не самая сложная, но достаточно точная для быстрой проверки адреса:
/^[A-Z0-9._%+-]+@[A-Z0-9-]+.+.[A-Z]{2,4}$/i
JS:
re.test('correct-email@mail.com'); // true
re.test('CORRECT.email@mail123.com'); //true
re.test('incorrect-email@mail'); //false
Что используем: Флаг i в регулярных выражений обеспечивает регистронезависимость сравнения.
3. Номер телефона#
Проверяя номер телефона, обязательно учитывайте общепринятые форматы, так как в разных странах их принято записывать по-разному. Например, для американского стиля подойдет вот такая регулярка:
/^\+?(\d{1,3})?[- .]?\(?(?:\d{2,3})\)?[- .]?\d\d\d[- .]?\d\d\d\d$/
JS:
re.test('(212) 348-2626'); // true
re.test('+1 832-393-1000'); // true
re.test('+1 202-456-11-11'); // false
Что используем: Квантификатор ? соответствует одному предыдущему символу или его отсутствию.
4. Надёжность пароля#
Часто встречаете на различных сервисах требование придумать сложный пароль? Кто и как определяет требуемую степень сложности? На самом деле, для этого есть некоторые стандарты: минимальная длина, разный регистр символов, наличие букв, цифр и специальных знаков.
Чтобы обеспечить ваших пользователей надежными паролями, можете воспользоваться вот таким выражением (или составить собственные регулярки со специфическими требованиями):
/^(?=.*[A-Z].*[A-Z])(?=.*[!@#$&*])(?=.*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{8,}$/
JS:
re.test('qwerty'); // false
re.test('qwertyuiop'); // false
re.test('abcABC123$'); // true
Что используем: Оператор ?= внутри скобочной группы позволяет искать совпадения “просматривая вперед” переданную строку и не включать найденный фрагмент в результирующий массив.
Подробнее о надежности паролей вы можете узнать из этого руководства.
5. Почтовый индекс (zip-code)#
Формат почтового индекса, как и телефона, зависит от конкретного государства.
В России все просто: шесть цифр подряд без разделителей.
/^\d{6}$/
Американский zip-code может состоять из 5 символов или в расширенном формате ZIP+4 – из 9.
/^\d{5}(?:[-\s]\d{4})?$/
JS:
re.test('75457'); // true
re.test('98765-4321'); // true
Что используем: Последовательность ?: внутри скобочной группы исключает ее из запоминания.
6. Номер кредитной карты#
Разумеется, при проверке номера платежной карты не стоит полагаться на регулярные выражения. Однако с их помощью вы можете сразу же отсеять очевидно неподходящие последовательности и не нагружать сервер лишним запросом.
С помощью вот такой длинной регулярки вы можете поддерживать сразу несколько платежных систем:
/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/
Подробнее разобраться, откуда что взялось, вы можете здесь.
Что используем: Вертикальная черта | в регулярных выражениях обозначает альтернацию, то есть выбор одного варианта из нескольких.
Распространенные форматы
7. Начальные и конечные пробелы#
Пробелы в начале и конце строки обычно не несут никакой смысловой нагрузки, но могут повлиять на анализ и обработку данных, поэтому от них следует сразу же избавляться.
/^[ \s]+|[ \s]+$/g
JS:
let str = " hello ";
console.log(str.length); // 7
str = str.replace(re, '');
console.log(str.length); // 5
Что используем: Квантификатор + соответствует инструкции {1,} – один и более символов.
8. Дата#
С датами приходится работать очень часто, а форматов записи у них великое множество. Прежде чем начинать обработку, имеет смысл проверить, соответствует ли вид переданной строки требуемому.
Вот такое регулярное выражение поддерживает несколько форматов дат – с полными и краткими числами (5-1-91 и 05-01-1991) и разными разделителями (точка, прямой или обратный слеш).
/^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[1,3-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$/
Здесь учитываются даже високосные годы!
JS:
re.test('29-02-2000'); // true
re.test('29-02-2001'); // false
Что используем: Последовательности вида \1, \2 и так далее – это обратные ссылки на скобочные группы, определяющие вид разделителя. Благодаря им можно отсеять даты с разными разделителями:
re.test('10-10/2010'); // false
9. IPv4#
Адрес IP используется для идентификации конкретного компьютера в интернете Он состоит из четырех групп цифр (байтов), разделенных точками (192.0.2.235).
/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/
Что используем: Класс \b означает “границу слова” и имеет нулевую ширину (то есть это не отдельный символ).
10. IPv6#
IPv6 – это новый, более сложный синтаксис IP-протокола. Выражение для проверки на этот формат выглядит куда страшнее, хотя на самом деле разница заключается только в поддержке шестнадцатеричных чисел:
(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))
11. Base64#
Base64 – достаточно распространенный формат кодирования бинарных данных, который часто используется, например, в email-рассылках.
Для валидации строки в этом формате можно использовать следующее регулярное выражение:
^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$
12. ISBN#
ISBN – международная номенклатура для печатных книг. Номер может состоять из 10 (ISBN-10) или 13 цифр (ISBN-13). На самих книгах ISBN обычно разделен дефисами на несколько групп (код страны, издательства и самой книги), но для проверки и использования их следует удалять.
Это регулярное выражение позволяет проверить оба формата сразу:
/\b(?:ISBN(?:: ?| ))?((?:97[89])?\d{9}[\dx])\b/i
JS:
re.test('ISBN 9781106998966'); // true
re.test('1106998966'); // true
re.test('110699896x'); // true
Числа
13. Проверка на число#
Очень простая проверка строки на число с помощью регулярок:
/^\d{1,}$/
JS:
re.test('13'); // true
re.test('23yy'); // false
14. Разделитель разрядов#
Задача разбить большое число на разряды по три цифры встречается в разработке довольно часто. Оказывается это очень легко сделать с помощью регулярок.
/\d{1,3}(?=(\d{3})+(?!\d))/g
JS:
'1234567890'.replace(re, '$&,'); // 1,234,567,890
Что используем: Комбинация $& в строке замены позволяет подставить найденную комбинацию.
15. Цена#
Цены могут быть представлены во множестве различных форматов. Универсального регулярного выражения для них, скорее всего, не существует, но цену в долларах из строки извлечь очень просто.
Эта регулярка предполагает, что для разделения разрядов числа используются запятые, а дробная часть отделена точкой:
/(\$[0-9,]+(\.[0-9]{2})?)/
JS:
let price = 'price $5,555.55'.match(re)[0]; '$5,555.55
Что используем: Комбинация {2} означает, что символ из диапазона [0-9] должен быть повторен ровно 2 раза (дробная часть цены).
Файлы и URL
16. Сопоставить строку URL#
Если вам необходимо проверить, является ли полученная строка URL-адресом, вы можете воспользоваться вот такой регуляркой:
/[-a-zA-Z0-9@:%_\+.~#?&\/=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&\/=]*)?/gi
Она подойдет для адресов с различными протоколами (HTTP, HTTPS, FTP) и даже без протокола.
JS:
re.test('https://yandex.ru'); // true
re.test('yandex.ru'); // true
re.test('hello world'); // false
17. Извлечение домена#
В URL-адресе много частей: протокол, домен, поддомены, путь к странице и строка запроса. С помощью регулярок можно отбросить все лишнее и получить только домен:
/https?:\/\/(?:[-\w]+\.)?([-\w]+)\.\w+(?:\.\w+)?\/?.*/i
JS:
let domain = 'https://proglib.io'.match(re);
console.log(domain[1]); // proglib
Что используем: Метод match возвращает объект с данными совпадения. Под индексом 1 в нем хранится совпадение, соответствующее первой скобочной группе.
18. Расширения#
Одна строчка регулярного выражения позволяет быстро и просто получить расширение файла, с которым вам предстоит работать:
/^(?:.*\.(?=(htm|html|class|js)$))?[^.]*$/i
JS:
let file1 = 'script.js'.match(re)[1]; // js
let file2 = 'hello'.match(re) [1]; // undefined
Разумеется, при необходимости сюда можно добавлять другие расширения.
19. Протокол#
Иногда требуется извлечь протокол полученной ссылки. Регулярные выражения и тут облегчают жизнь:
/^([a-zA-Z]+):\/\//
JS:
let protocol = 'https://proglib.io/'.match(re)[0]; // https
20. YouTube#
Получение ID видео на YouTube:
/https:\/\/(?:youtu\.be\/|(?:[a-z]{2,3}\.)?youtube\.com\/watch(?:\?|#\!)v=)([\w-]{11}).*/gi
JS:
re.exec('https://www.youtube.com/watch?v=JbgvaQ_rM4I')[1]; // JbgvaQ_rM4I
Что используем: Метод exec объекта регулярного выражения работает почти так же, как метод match строки.
HTML и CSS
21. HEX-цвета#
Веб-разработчику часто приходится иметь дело с цветами, заданными в шестнадцатеричном формате. Регулярки позволяют легко извлекать такие цвета из строки:
/\#([a-fA-F]|[0-9]){3, 6}/
Крутой рецепт, правда? :)
22. Адрес изображения#
Для получения адреса изображения обычно используется DOM-метод img.getAttribute(‘src’). Регулярки для этого применяются редко, но полезно все же знать их возможности:
/\< *[img][^\>]*[src] *= *[\"\']{0,1}([^\"\'\ >]*)/
JS:
re.exec('<img src="image.png" alt="image1">')[1]; // image.png
23. CSS-свойства#
Еще одна нетривиальная ситуация – получение свойств CSS с помощью регулярных выражений:
/\s*[a-zA-Z\-]+\s*[:]{1}\s[a-zA-Z0-9\s.#]+[;]{1}/gm
JS:
let css = ` .element {
color: white;
background: black;
font-size: 16px;
}`
css.match(re);
Что используем: Флаг m в регулярных выражениях включает многострочный режим.
24. HTML комментарии#
А это очень полезная регулярка для удаления комментариев из HTML-кода:
/<!--(.*?)-->/
Что используем? Символ ?, стоящий в регулярном выражении после другого квантификатора, переводит его в ленивый режим.
25. Title#
Получить заголовок веб-страницы можно с помощью такого регулярного выражения:
/<title>([^<>]*?)</title>/
26. rel=«nofollow»#
Важная SEO-задача, которую очень не хочется делать вручную, – добавление внешним ссылкам атрибута rel=“nofollow”. Обратимся к регулярным выражениям:
PHP:
$html = '<a href="https://site.com">site.com</a>,
<a href="my-site.com">my-site.com</a>,
<a href="https://site.com" rel="nofollow">site.com</a>';
$re = '/(<a\s*(?![^>]*\brel=)([^>]*\bhref=\"https?:\/\/[^"]+\"))/';
$result = preg_replace($re, '$1 rel="nofollow"', $html);
Эта регулярка выбирает в тексте все ссылки с протоколом http/https без атрибута rel и добавляет его.
27. Медиа запросы#
Если требуется проанализировать медиа-запросы CSS, воспользуйтесь этой регуляркой:
/@media([^{]+)\{([\s\S]+?})\s*}/g
Что используем: Класс \s обозначает пробельный символ (а также таб и перевод строки), а класс \S – наоборот, любой символ кроме пробельного.
28. Подсветка слов#
Полезное выражение для поиска и выделения слов в тексте:
/\b(ipsum)\b/ig
JS:
let text = 'Lorem ipsum dolor, lorem ipsum dolor.';
text.replace(re, '<span style="background: yellow">$&</span>')
PHP:
$re = '/\b(ipsum)\b/i';
$text = 'Lorem ipsum dolor, lorem ipsum dolor.';
preg_replace($re, '<span style="background:#5fc9f6">1</span>', $text);
Разумеется, слово ipsum можно заменить на любое другое слово или словосочетание
Другие задачи веб-разработчика
29. Проверка версии Internet Explorer#
К счастью, старый добрый IE постепенно уходит в прошлое, но он все же еще играет некоторую роль в современном вебе. Этот фрагмент кода позволяет определить версию всеми любимого браузера:
/^.*MSIE [5-8](?:\.[0-9]+)?(?!.*Trident\/[5-9]\.0).*$/
30. Удалить повторы#
Регулярки дают возможность автоматически удалить случайные повторы слов без проглядывания всего текста:
/(\w+)\s+\1/gi
JS:
"hello world world hello".replace(re, "$1") // hello world hello
31. Количество слов#
Порой веб-разработчику необходимо определить количество слов в строке, например, для организации ключевых слов в инструментах аналитики. Сделать это можно с помощью следующих регулярок:
^[^\s]*$ // ровно одно слово
^[^\s]*\s[^\s]*$ // ровно два слова
^[^\s]*\s[^\s]* // два слова и больше
^([^\s]*\s){2}[^\s]*$ // ровно три слова
^([^\s]*\s){4, }[^\s]*$ // пять слов и больше
32. Проверка ИНН (только цифры, и длина до 12 символов)#
/(^\d{1,12}$)/