Перейти к основному содержимому

Генератор regex

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

Эту форму описывает регулярное выражение. Генератор читает его слева направо и «набивает» каждый слот случайными символами из нужного набора, а литералы (дефисы, скобки, @) печатает как есть.

Конечное переносимое подмножество

Это не полный JavaScript RegExp. Это конечное подмножество, которое можно одинаково реализовать на каждом языке. Главное правило: результат должен иметь ограниченную длину, поэтому *, + и {n,} запрещены — верхнюю границу вы всегда пишете явно.

Разбор примера

Телефон в российском формате:

<gen type="regex" value="\+7 \(9[0-9]{2}\) [0-9]{3}-[0-9]{2}-[0-9]{2}"/>
./run phone.tdc
+7 (970) 701-63-46
+7 (968) 926-87-05
+7 (922) 609-13-68
+7 (927) 428-09-64
+7 (916) 957-20-83

Скобки, пробелы и дефисы — это литералы (обратный слеш перед ( и ) делает их обычными символами). \+7 — это литеральное +7, а 9[0-9]{2} и группы [0-9]{…} — слоты, куда подставляются случайные цифры. Форма всегда одна, значения — разные.

Все примеры на этой странице отрендерены с seed="demo" — с тем же сидом вы получите ровно те же строки. Значения в выводе иллюстративные: конкретные строки могут отличаться в зависимости от версии ядра, но форма — никогда.

Другие типовые формы:

ЗадачаПаттернПример
Артикул (SKU)[A-Z]{3}-[0-9]{4}SAH-0136
Номер авто (РФ)[АВЕКМНОРСТУХ][0-9]{3}[АВЕКМНОРСТУХ]{2}[0-9]{2,3}Т027ВМ384
Hex-токен на 32 символа[A-F0-9]{32}5AE5ABF3F7040BEB966D65A23EB7C1EC
Тестовый emailuser_[a-z0-9]{8}@test\.(com|org)user_zak0bdnw@test.com

Тот же артикул, отрендеренный целиком:

<gen type="regex" value="[A-Z]{3}-[0-9]{4}"/>
./run sku.tdc
SAH-0136
RVH-2608
GGA-0931
GSU-2840
DQN-5792

Когда обычный regex — правильный инструмент

Используйте type="regex", чтобы описать форму одной строки, когда вам не нужны точные пропорции внутри неё. Альтернатива вроде (com|org) выбирается случайно и независимо в каждой строке — этого достаточно, когда точное соотношение вариантов не важно.

Хорошие задачи для обычного regex:

  • технический ID: [A-Z]{2}[0-9]{6};
  • безопасный тестовый email: user_[a-z0-9]{8}@test\.(com|org);
  • код с повторяющимся блоком: ([0-9]{3})-[A-Z]{2}-\1;
  • токен фиксированной длины: [A-F0-9]{32}.

Если внутри строки нужны точные доли вариантов (например, ровно 70% с одним префиксом), обычный regex не подойдёт — используйте advanced_regex:

<gen type="advanced_regex" value="(?%{70:RU;20:US;10:DE})-[0-9]{6}"/>

Синтаксис вкратце

КонструкцияПримерЧто генерирует
ЛитералыABC-42Ровно эти символы
Экранированные символы\.\+\(\)\\Точка, плюс, скобки, обратный слеш
Классы символов[ABC], [a-z], [A-Z0-9]Один символ из набора
Unicode BMP-диапазон[а-я], [א-ת], [ぁ-ゖ]Один символ из диапазона
Именованный алфавит\a{kana.hiragana}Один символ из встроенного алфавита
Отрицательный класс[^0-9]Печатный ASCII-символ, кроме перечисленных
Сокращённый класс\d, \w, \sЦифра, word-символ, пробел/таб
Обратный сокращённый\D, \W, \SИнверсия предыдущего
Любой символ.Один печатный ASCII-символ
Альтернативаcat|dogcat или dog
Группа(cat|dog)Группировка и capture
Non-capturing группа(?:cat|dog)Группировка без capture
Backreference([0-9]{3})-\1Повторяет уже сгенерированную группу
OptionalAB?CAC или ABC
Точное повторение[A-Z]{4}Ровно 4
Диапазон повторений[A-Z]{2,5}От 2 до 5
Якоря^ABC$Нулевая ширина; результат ABC

Дальше — тот же список, но с реальным выводом под каждой конструкцией.

Классы символов

[…] берёт один случайный символ из набора. Диапазон a-z — сокращение для «все буквы от a до z».

<gen type="regex" value="[ABC]{6}"/> <!-- только A, B, C -->
<gen type="regex" value="[a-z]{6}"/> <!-- строчные латинские -->
<gen type="regex" value="[A-Z0-9]{6}"/> <!-- заглавные и цифры -->
./run demo.tdc
[ABC]{6}      [a-z]{6}      [A-Z0-9]{6}
CAACAA        sahtbc        ZAK0BD
CCACAC        rvhyfr        Y3K7HY
AAABAC        ggaqby        IJBWC8

Каждый слот выбирается независимо, поэтому в [ABC]{6} буквы повторяются — это не «выбор без повторений», а шесть отдельных случайных символов.

Сокращённые классы — \d \w \s

Готовые наборы: \d — цифра [0-9], \w — буква/цифра/_, \s — пробел или таб.

<gen type="regex" value="\d{6}"/>
<gen type="regex" value="\w{8}"/>
./run demo.tdc
\d{6}      \w{8}
702701     tBSvCGXm
682926     qyR7NqAz
220609     OQBoE7TG

\s невидим в выводе, поэтому здесь пробелы и табы показаны как <SP> и <TAB> (в реальном выводе это обычные пробел/таб):

<gen type="regex" value="A\sB\sC"/>
./run demo.tdc
A<TAB>B<TAB>C
A<SP>B<TAB>C
A<SP>B<SP>C

Отрицательные классы — [^…] \D \W \S

[^0-9] и \D дают любой печатный ASCII-символ, кроме перечисленных. Они эквивалентны и на одном сиде дают одинаковый вывод:

<gen type="regex" value="[^0-9]{6}"/>
<gen type="regex" value="\D{6}"/>
./run demo.tdc
[^0-9]{6}    \D{6}
f"Bi#)       f"Bi#)
cnAz<b       cnAz<b
@!"%zR       @!"%zR

Обратите внимание: набор — это весь печатный ASCII (буквы, цифры, знаки препинания), а не только буквы. Если нужна только «не-цифра из букв», задайте это явно: [A-Za-z].

Любой символ — .

Точка — это один печатный ASCII-символ (тот же набор, что у \D, только без исключений):

<gen type="regex" value=".{8}"/>
./run demo.tdc
c";g#*CZ
pl:y4_!m
69#&y=*Q
+ZO|Qdv7

Квантификаторы — сколько раз

{n} — ровно n; {n,m} — от n до m (случайно); ? — ноль или один раз (то есть AB?C — это AC или ABC).

<gen type="regex" value="[A-Z]{4}"/> <!-- ровно 4 -->
<gen type="regex" value="[A-Z]{2,5}"/> <!-- от 2 до 5 -->
<gen type="regex" value="AB?C"/> <!-- B необязательна -->
./run demo.tdc
[A-Z]{4}    [A-Z]{2,5}    AB?C
SAHT        SAHTB         ABC
RVHY        RVH           AC
GGAQ        GG            AC

Поменяйте квантификатор — изменится длина. Тот же «скелет» (буквы, потом цифры), но другого размера:

<gen type="regex" value="[A-Z]{2}[0-9]{4}"/> <!-- короткий -->
<gen type="regex" value="[A-Z]{3}[0-9]{8}"/> <!-- длинный -->
./run demo.tdc
[A-Z]{2}[0-9]{4}    [A-Z]{3}[0-9]{8}
SA7013              SAH01363846
RV9260              RVH26087805
GG6093              GGA09313068

Альтернатива и группы — | (…) (?:…)

cat|dog выбирает один вариант случайно в каждой строке. Скобки группируют варианты, чтобы к ним можно было приписать хвост или квантификатор.

<gen type="regex" value="cat|dog"/> <!-- альтернатива -->
<gen type="regex" value="(cat|dog)-[0-9]{2}"/> <!-- группа + хвост -->
<gen type="regex" value="(?:cat|dog)[0-9]"/> <!-- без capture -->
./run demo.tdc
cat|dog    (cat|dog)-[0-9]{2}    (?:cat|dog)[0-9]
dog        dog-02               dog7
cat        cat-82               cat6
cat        cat-20               cat2
dog        dog-77               dog2

Обычная группа (…) запоминает выбранное (capture) — на него потом можно сослаться через \1. (?:…) группирует, но ничего не запоминает; используйте её, когда захват не нужен.

Случайно, а не точно

cat и dog выпадают неравномерно — это случайный выбор, а не точные пропорции. Если нужны ровно 70/30, используйте advanced_regex.

Якоря — ^ $

Якоря ^ (начало) и $ (конец) имеют нулевую ширину: генератор их принимает, но в вывод они ничего не добавляют. ^[A-Z]{3}$ даёт те же три буквы, что и [A-Z]{3}:

<gen type="regex" value="^[A-Z]{3}$"/>
./run demo.tdc
SAH
RVH
GGA

Экранирование

Превратите метасимвол regex в обычный литерал через \:

<gen type="regex" value="\.\+\(\)\[\]\{\}\\"/>

Сгенерированная строка здесь постоянна (случайных слотов нет):

./run demo.tdc
.+()[]{}\

Внутри класса символов дефис — литерал, если он стоит первым или последним; тогда это просто символ -, а не диапазон:

<gen type="regex" value="[-A-C]{8}"/>
<gen type="regex" value="[A-C-]{8}"/>
./run demo.tdc
[-A-C]{8}    [A-C-]{8}
B-AB--AB     CABCAABC
BCAC-B-C     C-B-ACA-
-A-B-CA-     ABACA-BA

В наборе здесь четыре символа: A, B, C и -.

Unicode-алфавиты

Классы символов не ограничены ASCII. Тот же механизм принимает любой Unicode-диапазон BMP и любой встроенный именованный алфавит, поэтому генератор локализуется без особых случаев. Начните с латиницы, которая обычно нужна вашим данным, — обычный диапазон напрямую покрывает западноевропейские буквы с диакритикой:

<gen type="regex" value="[a-zà-ÿ]{8}"/> <!-- латиница + диакритика -->
./run demo.tdc
sàhtâbcé
rvïhyfrë
ggaçbÿnu

Примеры ниже — намеренная демонстрация Unicode и локализации: нелатинские письменности записываются так же. Обычные BMP-диапазоны работают прямо внутри класса символов:

<gen type="regex" value="[а-я]{8}"/> <!-- кириллица -->
<gen type="regex" value="[א-ת]{6}"/> <!-- иврит -->
./run demo.tdc
[а-я]{8}      [א-ת]{6}
цайчбглу      ףאחפבג
хщиюжхаъ      עץחשוע
зибфвюкг      זחאסבש

Для реальных конфигов именованные алфавиты понятнее — они документированы, валидируются по имени и могут включать символы, которые неудобно выразить диапазоном (например, русскую ё):

<gen type="regex" value="\a{cyrillic.ru.letters}{10}"/>
<gen type="regex" value="\a{kana.hiragana}{8}"/>
./run demo.tdc
\a{cyrillic.ru.letters}{10}    \a{kana.hiragana}{8}
нБСпВЖЧжХч                     まぃすめいおちふ
куСьНкАупф                     ほゆすをこぺあょ

Алфавиты можно смешивать внутри одного класса — тогда символ берётся из объединённого набора:

<gen type="regex" value="[\a{arabic.letters}\a{hebrew.letters}]{6}"/>
./run demo.tdc
חآشיؤב
הםشקدה
رسأבإק

Escape \a{name} — это один символ из указанного алфавита; он ведёт себя как любой атом: повторяйте его через {n} или {n,m}, а внутри класса он добавляет весь алфавит в набор. Полный список имён — на странице Symbol.

примечание

Отрицательные классы ([^...]), \D, \W, \S и . инвертируются только относительно печатного ASCII-набора. Для Unicode задавайте положительный набор явно через \a{name}.

Backreferences

Backreference связывает части строки между собой: \1 повторяет то, что уже сгенерировала первая группа (…).

<gen type="regex" value="([0-9]{3})-[A-Z]{2}-\1"/>
./run demo.tdc
702-BC-702
682-FR-682
220-BY-220
277-FW-277

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

Ссылка может указывать только на группу, уже сгенерированную слева от неё; прямая ссылка (forward-reference) — это ошибка:

<gen type="regex" value="\1([0-9]{3})"/>
./run bad.tdc
error: invalid regex generator pattern: backreference "\1" points to
a group that is not generated yet

Если capture находится внутри повторения, backreference использует последнее сгенерированное этой группой значение:

<gen type="regex" value="([A-Z]){3}-\1"/>
./run demo.tdc
SAH-H
RVH-H
GGA-A

Здесь ([A-Z]){3} прогоняет группу три раза, а \1 повторяет только третью произведённую букву.

Ограничение длины — regex_max_length

Каждый результат проверяется по regex_max_length (по умолчанию 32). Паттерн, который может её превысить, отклоняется до генерации:

<gen type="regex" value="[A-Z0-9]{40}"/>
./run token.tdc
error: invalid regex generator pattern: regex can produce 40 characters,
which exceeds regex_max_length=32

Поднимите лимит для всего конфига на <tdc>. Это удобно, когда в конфиге несколько длинных паттернов и вы хотите задать потолок в одном месте:

<tdc regex_max_length="64">
<env count="5" seed="demo">
<sequence name="Token"><gen type="regex" value="[A-Z0-9]{40}"/></sequence>
</env>
<block>
<line><data>${{Token}}</data></line>
</block>
</tdc>
./run token.tdc
MURI40FXS16A2ABROOBQFGMSDBLWP3TCDTA16VVK
NPJ3PVSU1NGARTRDQHT92IHGWJZVUST4531IOEAW
66WWVKTAA2XWUQJBJA8P0SNZ6W3Q75R3CP12JIXW

Или задайте его локально, только на этом генераторе, когда одно поле — исключение и вы не хотите ослаблять потолок для всего остального:

<gen type="regex" value="[A-Z0-9]{40}" regex_max_length="40"/>
./run token.tdc
MURI40FXS16A2ABROOBQFGMSDBLWP3TCDTA16VVK
NPJ3PVSU1NGARTRDQHT92IHGWJZVUST4531IOEAW
66WWVKTAA2XWUQJBJA8P0SNZ6W3Q75R3CP12JIXW

regex_max_length не делает бесконечный regex конечным — он лишь разрешает уже конечному результату быть длиннее.

Что запрещено

ЗапрещеноПочемуВместо этого
*Нет верхней границы{0,n}
+Нет верхней границы{1,n}
{n,}Нет верхней границы{n,m}
Lazy *?, ??Matcher-семантика, не генерацияЯвно задайте нужный диапазон
Lookahead / lookbehindПроверяет существующий текст, а не строитВынесите условие в DSL
Named capturesПока не реализованоОбычные группы и \1
Conditional groupsПока не реализованоИспользуйте <mix> или sequence
\p{...} / \P{...}Unicode properties пока не переносимы\a{name} или явный класс
\n / \rМногострочная генерация живёт в другом местеОтдельные <line>

Например, + отклоняется сразу:

<gen type="regex" value="[a-z]+"/>
./run bad.tdc
error: invalid regex generator pattern: unbounded "+" quantifier is not
allowed; use "{1,n}"

Точные пропорции

Обычный regex не задаёт проценты внутри выражения — (cat|dog) случайно, а не «ровно 70/30». Для точных долей используйте:

См. также

  • Advanced Regex — тот же движок плюс взвешенный выбор.
  • Symbol — когда нужен только набор символов, а не структура.
  • regex_max_length и alphabet.