Clases de caracteres en regex: \d, \w, \s, [a-z] y sus trampas
Las clases de caracteres son lo más usado de las regex y lo más fácil de equivocar sin darse cuenta. Con qué coinciden de verdad [abc], [a-z], [^…], \d, \w y \s, y las trampas que esconden: [A-z], el guion suelto, el punto entre corchetes y los dígitos que no van del 0 al 9.

· 8 min de lectura
/^[A-Z][a-z]+$/
atrapa
- Paris
- Lima
- Oslo
- Rome
deja libre
- paris
- PARIS
- New York
- R2D2
Una clase de caracteres coincide con un carácter de un conjunto. [aeiou] coincide con una vocal. [0-9] coincide con un dígito. \s coincide con un espacio, un tabulador o un salto de línea.
Aparecen en casi todos los patrones que vas a escribir, y la mayoría de sus trampas son silenciosas: el patrón funciona con las entradas que probaste y más adelante deja pasar algo raro. Este artículo cubre con qué coincide de verdad cada clase y después las trampas. Todos los ejemplos son interactivos, así que edita los patrones y mira cómo cambian las líneas.
01Un conjunto entre corchetes
Los corchetes enumeran los caracteres permitidos en una posición:
greay falla porque la clase ocupa exactamente un hueco. Para permitir más de un carácter, ponle un cuantificador detrás: [ae]+.
02Rangos
Un guion entre dos caracteres significa “todo lo que hay entre ellos”, según el código de carácter:
Puedes poner varios rangos y caracteres sueltos en una misma clase: [A-Za-z0-9_] son letras, dígitos y guion bajo.
03Clases negadas
Un ^ justo después del corchete de apertura invierte el conjunto: “cualquier carácter excepto estos”.
Ojo, porque “cualquier carácter excepto” significa de verdad cualquiera: espacios, dígitos, signos de puntuación y saltos de línea cuentan. 2024 coincide, porque los dígitos no son vocales.
Fuera de los corchetes, ^ es un ancla. Dentro, justo al principio, es una negación. En cualquier otra posición dentro de la clase es simplemente un acento circunflejo.
04Las abreviaturas
Algunas clases son tan comunes que tienen nombres cortos:
| Abreviatura | Significa (en JavaScript) | Opuesto |
|---|---|---|
\d |
un dígito, [0-9] |
\D |
\w |
un carácter de palabra, [A-Za-z0-9_] |
\W |
\s |
espacio en blanco: espacio, tabulador, salto de línea y compañía | \S |
. |
cualquier carácter excepto un salto de línea |
Dos de ellas sorprenden a la gente. \w incluye los dígitos y el guion bajo, así que no es “una letra”:
/^\w+$/Debe coincidir3/3
- hello
- snake_case
- R2D2
No debe2/2
- kebab-case
- two words
Y \s es más que un espacio: también coincide con tabuladores y saltos de línea. Si quieres exactamente un espacio, escribe un espacio.
05Trampa 1: [A-z] no es “todas las letras”
Los rangos siguen los códigos de carácter. Entre Z (90) y a (97) hay otros seis caracteres: [ \ ] ^ _ y el acento grave. Así que [A-z] los deja entrar:
Escribe los dos rangos por separado: [A-Za-z].
06Trampa 2: el guion en medio
Un guion entre dos caracteres crea un rango, aunque quisieras un guion literal:
Esa coma es el error: + es el código 43, . el 46, y la coma (44) queda en medio. Pon el guion al principio o al final de la clase, o escápalo, y vuelve a ser un guion normal:
07Trampa 3: el punto y otros caracteres especiales
La mayoría de los caracteres especiales pierden sus poderes dentro de los corchetes. [.] es un punto literal, [*+?] es uno de esos tres símbolos y [$] es un signo de dólar. Así que [.] es otra forma de escribir \.:
Dentro de una clase solo cuatro caracteres siguen siendo especiales: ], \, ^ al principio y - entre dos caracteres.
08Trampa 4: dígitos que no van del 0 al 9
En JavaScript, \d es exactamente [0-9]. En Python 3, con un patrón str normal, \d coincide con cualquier dígito Unicode: el arábigo-índico ٣, el devanagari ३, el de ancho completo 3. Lo mismo pasa con \w, que acepta letras de cualquier escritura.
import re
re.fullmatch(r"\d+", "٣٤٥") # matches in Python
re.fullmatch(r"\d+", "٣٤٥", re.ASCII) # None
Si un número va a acabar en int() o en una columna de una base de datos, eso importa. Usa [0-9], o el modificador re.ASCII, cuando quieras dígitos ASCII.
09Pruébalo
¿Puedes atrapar las líneas formadas solo por dígitos hexadecimales?
Atrapa las cadenas formadas solo por dígitos hexadecimales, en mayúsculas o minúsculas.
Objetivos · 0/6 atrapados
- ffobjetivo
- 00objetivo
- 1a2Bobjetivo
- DEADbeefobjetivo
- c0ffeeobjetivo
- 7objetivo
Inocentes · 0 errores
- fginocente
- 0x1finocente
- 12 34inocente
- beef!inocente
- gginocente
- zinocente
Escribe una regex: el tablero se actualiza mientras escribes.
10Lista de comprobación
[abc]coincide con un carácter del conjunto. Añade un cuantificador para más.[^abc]coincide con cualquier carácter que no esté en el conjunto, incluidos espacios y saltos de línea.- Escribe
[A-Za-z], nunca[A-z]. - Pon un guion literal al principio o al final:
[\w.-]. - Dentro de los corchetes,
.*+?$son literales. \wincluye los dígitos y_.\sincluye tabuladores y saltos de línea.- En Python,
\dy\wreconocen Unicode. Usa[0-9]ore.ASCIIpara limitarte a ASCII.
11Sigue practicando
- Castillos de caracteres y Patrulla de atajos son packs de práctica que entrenan justo esto.
- La guía tiene una sección completa sobre clases y abreviaturas.