Перейти к содержанию
Innovialabs

Регулярные выражения на практике: телефоны, email и URL

Практика3 мин

Коротко

Регулярка подходит для проверки формата, а не существования: телефон лучше нормализовать до цифр и проверить шаблоном, email — простым шаблоном плюс письмо-подтверждение, URL — встроенным парсером.

Короткий ответ

Регулярное выражение отвечает только на вопрос «похоже ли это на телефон, email или ссылку». Оно не скажет, существует ли номер, доходят ли письма и открывается ли сайт. Поэтому рабочая схема такая:

  1. Нормализовать ввод — убрать пробелы, скобки, дефисы.
  2. Проверить формат простым и понятным шаблоном.
  3. Подтвердить реальность — SMS-код, письмо со ссылкой, запрос к сайту.
  4. Повторить проверку на сервере: клиентскую валидацию легко обойти.

Телефоны Узбекистана (+998)

Номер в Узбекистане — это код страны 998 и ещё 9 цифр: двухзначный код оператора или региона и семь цифр абонента. Люди вводят его по-разному: +998 90 123 45 67, 998901234567, (90) 123-45-67.

Надёжнее всего сначала оставить только цифры, а уже потом проверять:

function normalizeUzPhone(input) {
  const digits = input.replace(/\D/g, "");
  if (/^998\d{9}$/.test(digits)) return "+" + digits;
  if (/^\d{9}$/.test(digits)) return "+998" + digits;
  return null;
}

normalizeUzPhone("(90) 123-45-67"); // "+998901234567"
normalizeUzPhone("12345");          // null

Если нужно проверить номер «как ввёл пользователь», без нормализации, подойдёт такой шаблон:

^(?:\+?998)?[\s-]?\(?\d{2}\)?[\s-]?\d{3}[\s-]?\d{2}[\s-]?\d{2}$

Храните номер в одном формате — +998XXXXXXXXX (E.164). Так проще искать дубликаты и передавать номер в SMS-шлюзы и CRM.

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

Email

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

const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

EMAIL_RE.test("user@example.com"); // true
EMAIL_RE.test("user@localhost");   // false
EMAIL_RE.test("user @mail.com");   // false

Он ловит опечатки — пропущенный @, пробелы, отсутствие домена — и не отсекает редкие, но допустимые адреса с +, дефисами или поддоменами. Существование ящика проверяется только письмом с подтверждением.

Типичная ошибка — слишком строгий шаблон вроде [a-z0-9.]+@[a-z]+\.[a-z]{2,3}. Он отклоняет адреса с +, домены из нескольких уровней и длинные доменные зоны.

URL

Для ссылок регулярка — плохой инструмент: у URL много частей, кодировок и крайних случаев. Используйте встроенный парсер и проверьте протокол:

function isHttpUrl(value) {
  try {
    const url = new URL(value);
    return url.protocol === "http:" || url.protocol === "https:";
  } catch {
    return false;
  }
}

Проверка протокола важна: без неё пройдут ссылки вида javascript:..., опасные для вставки в страницу. Если вы делаете редирект по ссылке из параметра, сверяйте url.hostname со списком разрешённых доменов.

Чтобы просто найти ссылки в тексте, например в сообщении чат-бота, достаточно грубого шаблона https?://[^\s<>"]+.

Где регулярки не справляются

  • Существование: номер, ящик и сайт могут быть корректными по формату, но не работать.
  • Международные адреса: домены и email на кириллице или других алфавитах часто не проходят ASCII-шаблоны.
  • Бизнес-правила: «только мобильные номера» или «только корпоративная почта» лучше проверять кодом, а не усложнять шаблон.
  • Безопасность: регулярка не защищает от XSS и SQL-инъекций — для этого нужно экранирование и параметризованные запросы.

Катастрофический бэктрекинг

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

^([a-z0-9]+\.?)+@

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

Как защититься:

  • Не вкладывайте квантификаторы над одними и теми же символами. Безопасная версия того же шаблона — ^[a-z0-9]+(?:\.[a-z0-9]+)*@: каждое повторение обязано начинаться с точки.
  • Ограничивайте длину ввода до запуска регулярки.
  • Проверяйте шаблоны на длинных «почти подходящих» строках в тестах.
  • Там, где шаблоны приходят извне, используйте движки с линейной сложностью, например RE2 или стандартный пакет regexp в Go.

Частые вопросы

Обычно достаточно проверить, что после 998 идут ровно 9 цифр. Жёсткий список кодов быстро устаревает; реальность номера лучше подтверждать SMS-кодом.

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.