База знаний

Regex-редиректы: одно правило вместо тысячи

У вас переезжает блог с тысячей статей. Старые URL вида /2021/08/15/nazvanie-stati должны стать /blog/nazvanie-stati. Создавать тысячу правил вручную — очевидно не вариант. Но и невозможно предусмотреть каждую статью заранее.

Regex-редиректы: одно правило вместо тысячи

Regex-редиректы решают именно это: одним правилом описывается шаблон, под который подпадают тысячи URL — и каждый перенаправляется корректно, сохраняя slug статьи.


Зачем нужны regex-редиректы

Обычный редирект — это отношение один-к-одному: конкретный URL источник → конкретный URL назначения. Это идеально для точечных случаев.

Regex-редирект — это отношение многие-к-одному-шаблону: любой URL, соответствующий паттерну, перенаправляется по правилу с подстановкой захваченных частей.

Типичные задачи, где без regex не обойтись:

  • Смена CMS — WordPress, Bitrix, 1С-Bitrix, Joomla, каждый со своей структурой URL. При переезде нужно перемапить тысячи страниц.
  • Удаление .html — сайт перешёл на ЧПУ, все старые страница.html должны вести на страница.
  • Реструктуризация каталога/catalog/category/subcategory/item/products/item.
  • Нормализация trailing slash — единообразно убрать или добавить слеш в конце.
  • Перенос блога — даты в URL стали ненужными, оставить только slug.

Синтаксис: минимум для работы

Для URL-редиректов достаточно знать небольшой набор конструкций:

СимволЗначениеПример
^Начало строки^/blog — URL начинается с /blog
$Конец строки/blog$ — URL заканчивается на /blog
.Любой символa.b — «a», любой символ, «b»
*Ноль или больше предыдущего.* — любая строка любой длины
+Один или больше предыдущего.+ — любая непустая строка
?Ноль или один предыдущий/blog/? — /blog или /blog/
\dЦифра (0–9)\d{4} — ровно 4 цифры
[^/]Любой символ кроме /[^/]+ — один сегмент пути
(...)Захватывающая группа([^/]+) — захватить сегмент
\Экранирование\.html — буквальная точка

Два правила, которые нарушают почти все при первом знакомстве с regex в URL:

Точка — это не точка. В regex . означает любой символ. Чтобы сопоставить буквальную точку (в расширении .html), нужно экранировать: \.html.

Слеш — это просто слеш. Он не имеет специального значения в regex (в отличие от некоторых других контекстов), поэтому экранировать его не нужно — хотя ошибки от лишних \/ обычно не возникает.


Захватывающие группы

Это ключевой механизм regex-редиректов. Часть паттерна, заключённая в скобки (...), запоминает совпавший текст. В URL назначения его можно вставить через $1, $2 и т.д. — по порядку открывающих скобок.

Пример с блогом:

Шаблон источника: ^/(\d{4})/(\d{2})/(\d{2})/([^/]+)$
URL назначения:   /blog/$4

Для URL /2021/08/15/nazvanie-stati:

  • $1 = 2021 (год)
  • $2 = 08 (месяц)
  • $3 = 15 (день)
  • $4 = nazvanie-stati (slug)

В итоге URL назначения: /blog/nazvanie-stati — год, месяц и день отброшены, slug сохранён.

Можно и объединять захваченное. Например, если нужен адрес /archive/2021/nazvanie-stati:

URL назначения: /archive/$1/$4

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


7 готовых шаблонов

1. Удаление дат из URL блога

Источник: ^/\d{4}/\d{2}/\d{2}/([^/]+)/?$
Назначение: /blog/$1

Работает для /2021/08/15/statya, /2019/01/01/drugaya-statya и т.д.


2. Удаление расширения .html

Источник: ^/(.+)\.html$
Назначение: /$1

/about.html/about, /catalog/item.html/catalog/item. Точка экранирована — иначе совпало бы с /about_html.


3. Перенос раздела каталога

Источник: ^/catalog/old-category/([^/]+)/?$
Назначение: /products/new-category/$1

Все URL из старой категории → новая. Slug товара сохраняется.


4. Нормализация trailing slash (добавить)

Источник: ^(/[^.]*[^/])$
Назначение: $1/

Добавляет слеш к URL без расширения файла. /about/about/, но /style.css не трогает.


5. Перенос вложенного пути целиком

Источник: ^/old-section/(.*)$
Назначение: /new-section/$1

/old-section/page/new-section/page, /old-section/sub/page/new-section/sub/page. (.*) захватывает весь остаток пути включая вложенность.


6. Извлечение параметра из пути

Источник: ^/products/id-(\d+)/?$
Назначение: /catalog/item?id=$1

/products/id-12345/catalog/item?id=12345. Числовой ID извлекается из slug и передаётся как query-параметр.


7. Двойной захват: перестановка сегментов

Источник: ^/([^/]+)/([^/]+)/?$
Назначение: /$2/$1

Меняет местами два сегмента пути. /category/subcategory/subcategory/category. Используйте осторожно — паттерн очень широкий, захватит больше чем кажется.


Типичные ошибки

Незаякоренный шаблон. Без ^ в начале паттерн /blog/ сопоставится с любым URL, который содержит /blog/ в любом месте — включая /archive/blog/post. Всегда начинайте с ^.

Жадный .* там, где нужен [^/]+. Паттерн ^/([^/]+)/(.*)$ для /a/b/c захватит a в $1 и b/c в $2. А ^/(.*)/(.*)$ — непредсказуемо, потому что жадный .* попытается захватить максимум, и второй (.*) может оказаться пустым. Для сегментов пути используйте [^/]+.

Точка без экранирования. \.html и .html — разные вещи. Без экранирования /aboutXhtml тоже совпадёт.

Слишком широкий шаблон выше специфичного. Если ^/(.*)$ стоит раньше ^/blog/(.*)$ — второе правило никогда не сработает. Специфичные правила должны быть выше.

Бесконечный цикл. Шаблон ^/(.*)$/$1 никуда не редиректит — URL назначения совпадает с источником. Некоторые системы это поймают, другие — войдут в цикл.


Как тестировать

Перед применением на продакшене обязательно проверьте каждое правило против набора реальных URL.

regex101.com — стандартный инструмент. Вставляете шаблон, пишете тестовые строки, видите совпадения и захваченные группы в реальном времени. Выбирайте режим PCRE2.

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

  • Типичный URL, который должен совпасть
  • URL с trailing slash и без
  • URL со спецсимволами и кириллицей
  • URL, который не должен совпасть — убедитесь, что не совпадает
  • Самый длинный и самый короткий возможный URL

После тестирования regex — проверьте финальный редирект через тестер редиректов. Иногда шаблон работает корректно, но URL назначения собирается неправильно из-за опечатки в $1/$2.

Хорошее правило: развёртывайте regex-правила по одному и мониторьте 404 в первые часы. Один неверный шаблон может накрыть большой раздел сайта.

Часто задаваемые вопросы

Когда нужны regex-редиректы вместо обычных?
Когда структура старых URL подчиняется закономерности, которую можно описать шаблоном. Тысяча страниц блога с датами в URL, товарный каталог со старой структурой, удаление .html у всех страниц — всё это одно regex-правило вместо тысячи отдельных.
Что такое захватывающая группа?
Часть regex в скобках (...), которая запоминает совпавший текст. Её значение можно подставить в URL назначения через $1, $2 и т.д. Например, шаблон ^/blog/(.*) захватит slug статьи, и /articles/$1 подставит его в новый адрес.
Чем отличается .* от .+?
.* означает 'ноль или больше любых символов' — совпадает в том числе с пустой строкой. .+ означает 'один или больше' — пустая строка не совпадёт. Для обязательных сегментов URL используйте .+, для опциональных — .*
Что такое жадное и нежадное совпадение?
По умолчанию .* 'жадный' — захватывает как можно больше. .+? — 'нежадный', останавливается при первом совпадении. Для URL-сегментов часто лучше использовать [^/]+ — 'всё кроме слеша', что точнее выражает намерение.
Можно ли в regex создать данные, которых нет в URL?
Нет. Regex может перегруппировать, отбросить или трансформировать части существующего URL, но не может добавить информацию, которой в нём нет. Если старый URL не содержит категорию, regex не сможет её подставить.
Порядок правил имеет значение?
Да. Правила применяются сверху вниз, первое совпавшее выигрывает. Более специфичные правила должны быть выше общих — иначе общий шаблон перехватит URL раньше специфичного.
Как проверить regex до применения на проде?
Используйте regex101.com — вставляете шаблон и тестируете против набора URL. Обязательно проверяйте крайние случаи: URL с/без trailing slash, с параметрами, вложенные пути.

Связанные материалы

Regex-редиректы без сервера

redirekto.ru поддерживает полноценные regex-правила на уровне DNS. Один шаблон покрывает тысячи URL — без Nginx, без .htaccess, без деплоя.

Попробовать бесплатно
A B

платформа редиректов

редиректо.ru

Включайте предсказуемую маршрутизацию доменов: DNS, HTTPS и контроль правил в одной панели.