Saltar al contenido principal

El generador regex

Se usa cuando un valor tiene una forma estricta — un número de teléfono, un SKU, una placa de auto, un token, un código de pedido. Hay demasiadas posibilidades para una lista, y demasiada estructura interna para number: letras, dígitos y separadores en lugares determinados.

Una expresión regular describe esa forma. El generador la lee de izquierda a derecha y llena cada hueco con caracteres aleatorios del conjunto correcto, imprimiendo los literales (guiones, paréntesis, @) tal cual.

Un subconjunto finito y portable

Esto no es el RegExp completo de JavaScript. Es un subconjunto finito que se puede implementar de forma idéntica en cada lenguaje. La única regla dura: el resultado debe tener una longitud acotada, así que *, + y {n,} no están permitidos — siempre se escribe un tope superior explícito.

Un ejemplo desarrollado​

Un número de teléfono en formato estadounidense:

<gen type="regex" value="\+1 \([0-9]{3}\) [0-9]{3}-[0-9]{4}"/>
./run phone.tdc
+1 (299) 994-1396
+1 (929) 818-7014
+1 (462) 860-3781
+1 (905) 009-2500
+1 (876) 318-9991

Los paréntesis, los espacios y los guiones son literales (la barra invertida antes de ( y ) los convierte en caracteres comunes). El \+1 es un +1 literal, y los grupos [0-9]{…} son huecos que reciben dígitos aleatorios. La forma es siempre la misma; los valores cambian.

Todos los ejemplos de esta página se renderizan con seed="demo". Pero el sorteo lo deciden dos cosas, y la segunda sorprende: la semilla y el nombre de la secuencia. Cada columna saca de su propio flujo, derivado de ambos, para que agregar una columna nunca desplace a las de al lado — así que el mismo patrón bajo <sequence name="Phone"> y bajo <sequence name="V"> da strings distintos con la misma semilla. Si copia un patrón de esta página a una secuencia con otro nombre, espere otros valores.

Los valores de salida son ilustrativos; los strings exactos pueden cambiar según la versión del core, pero la forma nunca.

Otras formas de todos los días:

TareaPatrónEjemplo
SKU[A-Z]{3}-[0-9]{4}SAH-0136
Placa (EE. UU.)[0-9][A-Z]{3}[0-9]{3}7KLM042
Token hex de 32 caracteres[A-F0-9]{32}5AE5ABF3F7040BEB966D65A23EB7C1EC
Correo de pruebauser_[a-z0-9]{8}@test\.(com|org)user_zak0bdnw@test.com

Ese mismo SKU, renderizado completo:

<gen type="regex" value="[A-Z]{3}-[0-9]{4}"/>
./run sku.tdc
FZY-9944
YHZ-8189
LRG-8608
YAO-0097
WTR-3189

Cuándo el regex simple es la herramienta correcta​

Use type="regex" para describir la forma de un string cuando no se necesitan proporciones exactas dentro de él. Una alternancia como (com|org) se elige al azar y de forma independiente en cada fila — está bien cuando el reparto exacto de las variantes no importa.

Buenos trabajos para el regex simple:

  • un ID técnico: [A-Z]{2}[0-9]{6};
  • un correo de prueba seguro: user_[a-z0-9]{8}@test\.(com|org);
  • un código con un bloque que se repite: ([0-9]{3})-[A-Z]{2}-\1;
  • un token de longitud fija: [A-F0-9]{32}.

Si se necesitan porciones exactas de variantes dentro del string (digamos, exactamente 70 % con un prefijo), el regex simple no lo hace — eche mano de advanced_regex:

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

La sintaxis de un vistazo​

ConstrucciónEjemploGenera
LiteralesABC-42Exactamente esos caracteres
Caracteres escapados\.\+\(\)\\Punto, más, paréntesis, barra invertida
Clase de caracteres[ABC], [a-z], [A-Z0-9]Un carácter del conjunto
Rango Unicode BMP[а-я], [א-ת], [ぁ-ゖ]Un carácter del rango
Alfabeto con nombre\a{kana.hiragana}Un carácter de un alfabeto incorporado
Clase negada[^0-9]Un carácter ASCII imprimible, salvo esos
Clase abreviada\d, \w, \sDígito, carácter de palabra, espacio o tabulador
Abreviada inversa\D, \W, \SLo inverso de lo anterior
Cualquier carácter.Un carácter ASCII imprimible
Alternanciacat|dogcat o dog
Grupo(cat|dog)Agrupación y captura
Grupo sin captura(?:cat|dog)Agrupación sin captura
Retrorreferencia([0-9]{3})-\1Repite un grupo ya generado
Grupo con nombre(?<code>[A-Z]{2})Agrupación y captura, bajo un nombre
Referencia por nombre\k<code>Repite un grupo por su nombre
Condicional(?(code)-|/)Una rama u otra, según el grupo
OpcionalAB?CAC o ABC
Repetición exacta[A-Z]{4}Exactamente 4
Repetición por rango[A-Z]{2,5}De 2 a 5
Anclas^ABC$Ancho cero; el resultado es ABC

El resto de esta página es la misma lista, pero con salida real debajo de cada entrada.

Clases de caracteres​

[…] toma un carácter al azar del conjunto. Un rango a-z es la forma corta de decir todas las letras de la a a la z.

<gen type="regex" value="[ABC]{6}"/> <!-- solo A, B, C -->
<gen type="regex" value="[a-z]{6}"/> <!-- latinas minúsculas -->
<gen type="regex" value="[A-Z0-9]{6}"/> <!-- mayúsculas y dígitos -->
./run demo.tdc
[ABC]{6}      [a-z]{6}      [A-Z0-9]{6}
CAACAA        sahtbc        ZAK0BD
CCACAC        rvhyfr        Y3K7HY
AAABAC        ggaqby        IJBWC8

Cada hueco se elige de forma independiente, así que las letras se repiten en [ABC]{6} — son seis caracteres aleatorios por separado, no una selección sin repetición.

Clases abreviadas — \d \w \s​

Conjuntos listos para usar: \d es un dígito [0-9], \w es una letra, un dígito o _, y \s es un espacio o un tabulador.

<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 es invisible en la salida, así que aquí los espacios y tabuladores se muestran como <SP> y <TAB> (en la salida real son espacios en blanco comunes):

<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

Clases negadas — [^…] \D \W \S​

[^0-9] y \D dan cualquier carácter ASCII imprimible excepto los listados. Son equivalentes y producen la misma salida con la misma semilla:

<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

Note que el conjunto es todo el ASCII imprimible (letras, dígitos, puntuación), no solo letras. Si lo que quiere es únicamente una letra que no sea dígito, escríbalo explícitamente: [A-Za-z].

Cualquier carácter — .​

El punto es un carácter ASCII imprimible (el mismo conjunto que \D, sin exclusiones):

<gen type="regex" value=".{8}"/>
./run demo.tdc
3|{Dy{JH
z9{Gl0mx
J^9Pp_%r
z!Tx'){i

Cuantificadores — cuántas veces​

{n} es exactamente n; {n,m} es de n a m (al azar); ? es cero o uno (así que AB?C es AC o ABC).

<gen type="regex" value="[A-Z]{4}"/> <!-- exactamente 4 -->
<gen type="regex" value="[A-Z]{2,5}"/> <!-- de 2 a 5 -->
<gen type="regex" value="AB?C"/> <!-- B opcional -->
./run demo.tdc
[A-Z]{4}    [A-Z]{2,5}    AB?C
SAHT        SAHTB         ABC
RVHY        RVH           AC
GGAQ        GG            AC

Cambie el cuantificador y cambia la longitud — mismo esqueleto (letras y luego dígitos), distinto tamaño:

<gen type="regex" value="[A-Z]{2}[0-9]{4}"/> <!-- corto -->
<gen type="regex" value="[A-Z]{3}[0-9]{8}"/> <!-- largo -->
./run demo.tdc
[A-Z]{2}[0-9]{4}    [A-Z]{3}[0-9]{8}
SA7013              SAH01363846
RV9260              RVH26087805
GG6093              GGA09313068

Alternancia y grupos — | (…) (?:…)​

cat|dog elige una variante al azar en cada fila. Los paréntesis agrupan variantes para poder pegarles un sufijo o un cuantificador.

<gen type="regex" value="cat|dog"/> <!-- alternancia -->
<gen type="regex" value="(cat|dog)-[0-9]{2}"/> <!-- grupo + sufijo -->
<gen type="regex" value="(?:cat|dog)[0-9]"/> <!-- sin captura -->
./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

Un grupo simple (…) recuerda su elección (la captura), así que se puede volver a él con \1. (?:…) agrupa sin recordar — úselo cuando no necesite la captura.

Aleatorio, no exacto

cat y dog salen de forma despareja — es una elección aleatoria, no una proporción exacta. Para exactamente 70/30, use advanced_regex.

Anclas — ^ $​

^ (inicio) y $ (fin) son de ancho cero: el generador las acepta pero no agregan nada a la salida. ^[A-Z]{3}$ produce las mismas tres letras que [A-Z]{3}:

<gen type="regex" value="^[A-Z]{3}$"/>
./run demo.tdc
FZY
YHZ
LRG

Escapado​

Convierta un metacarácter de regex en un literal común con \:

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

Aquí el string generado es constante (no hay huecos aleatorios):

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

Dentro de una clase de caracteres, un guion es un literal cuando va primero o último — entonces es solo el carácter -, no un rango:

<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

El conjunto aquí son cuatro caracteres: A, B, C y -.

Alfabetos Unicode​

Las clases de caracteres no están limitadas a ASCII. La misma maquinaria acepta cualquier rango Unicode BMP y cualquier alfabeto con nombre incorporado, así que el generador se localiza sin casos especiales. Empiece por la escritura latina que sus datos suelen necesitar — un rango simple cubre directamente las letras acentuadas de Europa occidental:

<gen type="regex" value="[a-zà-ÿ]{8}"/> <!-- latinas + acentos -->
./run demo.tdc
lþýwüýzy
ýpþyôkõü
zìpãöídø

Los ejemplos de abajo son una demostración deliberada de Unicode y localización — escrituras no latinas escritas de la misma manera. Los rangos BMP simples funcionan directamente dentro de una clase de caracteres:

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

Para configuraciones reales, los alfabetos con nombre son más claros — están documentados, validados por su nombre y pueden incluir caracteres incómodos de expresar como rango (como la ё rusa):

<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}
нБСпВЖЧжХч                     まぃすめいおちふ
куСьНкАупф                     ほゆすをこぺあょ

Se pueden mezclar alfabetos dentro de una misma clase — el carácter se toma entonces de la unión:

<gen type="regex" value="[\a{arabic.letters}\a{hebrew.letters}]{6}"/>
./run demo.tdc
خררػקר
קسרؾםح
ؿדسلנה

El escape \a{name} es un carácter de ese alfabeto y se comporta como cualquier átomo — repítalo con {n} o {n,m}; dentro de una clase agrega el alfabeto completo al conjunto. La lista completa de nombres está en la página Symbol.

nota

Las clases negadas ([^...]), \D, \W, \S y . invierten únicamente contra el conjunto ASCII imprimible. Para Unicode, escriba un conjunto positivo con \a{name}.

Retrorreferencias​

Una retrorreferencia ata entre sí partes de un string: \1 repite lo que el primer grupo (…) ya generó.

<gen type="regex" value="([0-9]{3})-[A-Z]{2}-\1"/>
./run demo.tdc
299-YZ-299
929-UE-929
462-VR-462
905-BC-905

Los primeros y los últimos tres dígitos siempre coinciden — ese es el bloque capturado. Así se construyen números de documento donde una sección se repite.

Una referencia solo puede apuntar a un grupo ya generado a su izquierda; una referencia hacia adelante es un error:

<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

Si la captura está dentro de una repetición, la retrorreferencia usa el último valor que ese grupo generó:

<gen type="regex" value="([A-Z]){3}-\1"/>
./run demo.tdc
FZY-Y
YHZ-Z
LRG-G

Aquí ([A-Z]){3} corre el grupo tres veces, y \1 repite solo la tercera letra que produjo.

Grupos con nombre — (?<name>…)​

Un grupo puede llevar un nombre, y \k<name> lo repite. Es el mismo grupo que repite \1: el nombre es una segunda forma de llegar a un grupo, no un segundo grupo.

<gen type="regex" value="(?<code>[A-Z]{2})-[0-9]{3}-\k<code>"/>
./run demo.tdc
FZ-399-FZ
YH-481-YH
LR-586-LR
YA-900-YA

Un nombre hace legible un patrón largo, y es lo que lee un condicional. Tres reglas:

  • Un nombre empieza por una letra o _ y lleva letras, dígitos y _.
  • Un nombre se usa una sola vez. Dos grupos bajo un mismo nombre convertirían \k<name> en un volado, resuelto por el que el analizador registró al final.
  • \k<name> solo puede nombrar un grupo ya cerrado — la misma regla que sigue \1.

(?<=…) y (?<!…) siguen siendo lookbehind y siguen rechazados. Ninguno es un grupo cuyo nombre empiece por =.

Condicionales — (?(name)sí|no)​

Un condicional pregunta si un grupo produjo algo y escribe una rama u otra. Así se pone un separador solo cuando hay algo que separar:

<gen type="regex" value="(?<area>0[1-9]{2})?(?(area)-|8 )[0-9]{4}"/>
./run demo.tdc
099-9944
039-8189
063-8608
016-0097
8 7683
8 0194

El código de área es opcional. Donde aparece lo sigue un -; donde no, la fila empieza con 8 . Sin un condicional eso son dos configuraciones, o un <switch>.

  • El condicional no gasta azar. Lee una decisión que el grupo ya tomó, así que añadir uno a un patrón deja el resto de los valores de la columna donde estaban.
  • La segunda rama se puede omitir: (?(area)-) escribe el - o nada en absoluto.
  • Un grupo también se puede probar por número — ([0-9]{3})?(?(1)-).
  • Dos ramas, no más. Una tercera se rechaza en vez de descartarse en silencio; si hace falta una elección dentro de una rama, agrúpela: (?(area)(?:x|y)|z).

Un condicional solo puede probar un grupo que esté a su izquierda, por la misma razón que una retrorreferencia: el grupo todavía no ha producido nada, así que esa rama nunca podría tomarse.

<gen type="regex" value="(?(area)-)(?<area>[0-9]{3})"/>
./run bad.tdc
error: invalid regex generator pattern: conditional group "(?(area)...)"
tests group "area", which is not generated yet

El límite de longitud — regex_max_length​

Cada resultado se contrasta con regex_max_length (por omisión 32). Un patrón que pudiera excederlo se rechaza antes de generar:

<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

Suba el tope para toda la configuración en <tdc>. Use esto cuando una configuración tiene varios patrones largos y quiere fijar el techo en un solo lugar:

<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

O fíjelo localmente, solo en este generador, cuando un único campo es la excepción y no quiere aflojar el techo en todos los demás:

<gen type="regex" value="[A-Z0-9]{40}" regex_max_length="40"/>
./run token.tdc
H88N88QPEO7XQU8Y3HSZVUVHBRNYDL22R5UYULFK
8J8P2G372CFQ09IGKO4DBWVJ7OX20A24XAGFOCA2
PXJS4YC5M13GUWUS7BVTYLT6Y3YFXOC04TLQUFZF

regex_max_length no vuelve finita una regex infinita — solo permite que un resultado ya finito sea más largo.

Qué no está permitido​

No permitidoPor quéUse en su lugar
*Sin tope superior{0,n}
+Sin tope superior{1,n}
{n,}Sin tope superior{n,m}
Perezosos *?, ??Semántica de búsqueda, no de generaciónEscriba el rango que quiere
Lookahead / lookbehindInspeccionan texto existente, no lo construyenMueva la condición al DSL
\p{...} / \P{...}Las propiedades Unicode aún no son portables\a{name} o una clase explícita
\n / \rLa generación multilínea vive en otro ladoUse <line>s separados

Por ejemplo, + se rechaza de inmediato:

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

Valores únicos — uniq="true"​

Un patrón siempre es finito — *, + y {n,} no se permiten —, así que se puede contar, y uniq="true" en su secuencia da a cada fila una cadena distinta:

<sequence name="Plate" uniq="true">
<gen type="regex" value="[A-Z]{2}-[0-9]{4}"/>
</sequence>

La cuenta sale de la forma del patrón: una clase aporta sus caracteres, una secuencia multiplica, | suma y {m,n} suma cada longitud que permite. [A-Z]{2}-[0-9]{4} son 26² · 10⁴ = 6 760 000 matrículas; si se piden más filas, la corrida se rehúsa antes de sacar nada y nombra ambos números. Dentro de esa cuenta, el sorteo simplemente se repite cada vez que cae en una matrícula ya entregada.

Un patrón de longitud variable agota primero sus formas cortas. {2,10} elige cada una de sus nueve longitudes una vez de cada nueve, así que [0-9]{2,10}, al pedirle 200 000 valores únicos, entrega las cien cadenas de dos dígitos y las mil de tres, y el resto de la columna es más largo. La unicidad desplaza la mezcla de longitudes; no rechaza la petición.

Cuando a una misma cadena se llega por dos caminos — (a|ab)(c|bc) produce abc por ambos —, la cuenta queda alta, y una petición cercana a ella puede superar las cadenas que existen de verdad. El sorteo nota que las repeticiones se acumulan y se detiene con el motivo, en lugar de quedarse en un bucle.

Proporciones exactas​

El regex simple no fija porcentajes dentro de la expresión — (cat|dog) es aleatorio, no exactamente 70/30. Para porciones exactas use:

Vea también​