Menu

Tutorial de regex en Python: módulo re, patrones, grupos y reemplazo

Una introducción práctica al módulo re de Python — buscar, hacer match, capturar grupos, reemplazar y los patrones a los que más recurrirás.

Cuándo recurrir a regex

Las expresiones regulares son un pequeño lenguaje para describir patrones de texto. Son potentes y fáciles de usar en exceso.

Antes de recurrir a re, pregúntate si los métodos de string planos lo harían. .split(), .replace(), .startswith(), "target" in text — son más rápidos, más legibles y menos propensos a error que la regex equivalente. Guarda regex para cuando el patrón que te importa sea genuinamente estructurado pero demasiado flexible para operaciones fijas de string: direcciones de email, números de teléfono, líneas de log con formas conocidas, snippets de HTML o Markdown, cualquier búsqueda "encuentra este tipo de cosa".

El vocabulario básico

Un patrón regex es un string que describe lo que estás buscando. Unos cuantos bloques de construcción:

  • . — cualquier carácter único
  • \d — cualquier dígito (0–9)
  • \w — cualquier carácter de "palabra" (letra, dígito, guion bajo)
  • \s — cualquier carácter de espacio en blanco
  • ^ — inicio del string
  • $ — fin del string
  • [abc] — cualquiera de a, b o c
  • [^abc] — cualquier carácter excepto a, b, c
  • a|b — a o b
  • * — cero o más de lo anterior
  • + — uno o más
  • ? — cero o uno
  • {3} — exactamente 3
  • {2,5} — entre 2 y 5
  • ( ... ) — grupo (captura la coincidencia de dentro)

Eso es suficiente para la mayoría de regex del mundo real.

Las funciones clave

re.search(pattern, text) encuentra la primera coincidencia en cualquier sitio del string. Devuelve un objeto match o None:

main.py
Output
Click Run to see the output here.

Usa siempre un string raw (r"...") para patrones regex. Si no, Python intenta interpretar las barras invertidas como escapes de string y obtienes un patrón distinto al que tecleaste.

re.match(pattern, text) es como search pero solo hace match al principio:

main.py
Output
Click Run to see the output here.

La mayor parte del tiempo quieres search.

re.findall(pattern, text) devuelve todas las coincidencias no solapadas como lista:

main.py
Output
Click Run to see the output here.

Fíjate en que findall devuelve strings, no objetos match. Si tienes un patrón con un grupo, obtienes el contenido del grupo. Con varios grupos, obtienes una lista de tuplas.

Grupos de captura

Los paréntesis en un patrón capturan lo que haya coincidido dentro:

main.py
Output
Click Run to see the output here.

Los grupos con nombre suelen ser más claros:

main.py
Output
Click Run to see the output here.

Una vez que la regex tiene más de un grupo, nombrarlos hace el código de extracción mucho más fácil de seguir.

Reemplazar con re.sub

re.sub(pattern, replacement, text) reemplaza cada coincidencia:

main.py
Output
Click Run to see the output here.

Eso quita todo lo que no sea un dígito. El reemplazo puede referenciar grupos capturados con \1, \2, etc. — o en strings raw, \g<1> es más claro:

main.py
Output
Click Run to see the output here.

También puedes pasar una función como reemplazo. Eso es útil para transformaciones que no son un simple intercambio:

main.py
Output
Click Run to see the output here.

Compilar patrones para reutilizar

Si usas el mismo patrón muchas veces — especialmente en un bucle — compílalo una vez:

main.py
Output
Click Run to see the output here.

Los patrones compilados exponen los mismos métodos — search, match, findall, sub — sin el patrón como primer argumento. Ligeramente más eficiente, a menudo más legible.

Flags

Modificadores comunes, pasados como argumento flags= u OR'd juntos:

  • re.IGNORECASE (re.I) — coincidencia sin distinguir mayúsculas.
  • re.MULTILINE (re.M) — ^ y $ coinciden en cada línea, no solo en los límites del string.
  • re.DOTALL (re.S) — . coincide también con saltos de línea (por defecto no).
  • re.VERBOSE (re.X) — permite espacios en blanco y comentarios # en el patrón, para legibilidad.
main.py
Output
Click Run to see the output here.

re.VERBOSE es especialmente útil para patrones complejos:

main.py
Output
Click Run to see the output here.

Las regex multilínea y comentadas son muchísimo más fáciles de mantener que one-liners opacos.

Greedy vs lazy

Los cuantificadores (*, +, ?, {n,}) son greedy por defecto — hacen match de tanto como puedan. Añade un ? para hacerlos lazy:

main.py
Output
Click Run to see the output here.

La versión greedy captura toda la subcadena desde <b> hasta </i> — probablemente no lo que querías. El .+? lazy para en el primer >.

(Nota al margen: no parsees HTML con regex en producción. Usa html.parser o BeautifulSoup. El ejemplo de arriba es solo para ilustrar la greediness.)

Un ejemplo realista

Parsear líneas de un formato de log simple:

main.py
Output
Click Run to see the output here.

Eso es mucha potencia en no muchas líneas.

Unos cuantos hábitos

  • Usa siempre strings raw para patrones.
  • Empieza con el patrón más simple que funcione; afínalo después.
  • Usa grupos con nombre cuando tengas más de un grupo.
  • Compila los patrones que vayas a reutilizar.
  • Regex es más lento que los métodos planos de string. Si .split() sirve, usa .split().

Siguiente: errores y depuración

Eso cierra el tour de datos reales — archivos, JSON, CSV, HTTP, fechas y regex. Cualquier cosa en un programa real tarde o temprano se topa con un error, eso sí, y leer bien los tracebacks de Python es la habilidad de depuración más importante que puedes coger. El último capítulo cubre excepciones y los errores específicos con los que te encontrarás más a menudo.

Preguntas frecuentes

¿Qué es regex en Python?

Una expresión regular (regex) es un pequeño lenguaje para describir patrones en texto. El módulo re de Python te deja buscar patrones, extraer piezas y reemplazar coincidencias. Es excesivo para operaciones simples de string — usa métodos de string como .split() o .replace() primero — pero insuperable para coincidencias estructuradas de patrones.

¿Cuál es la diferencia entre re.match y re.search?

re.match solo hace match al principio del string. re.search escanea el string entero y encuentra la primera coincidencia en cualquier sitio. En caso de duda, usa search — coincide mejor con la intuición humana.

¿Debería usar siempre strings raw para patrones regex?

Sí. Los patrones regex a menudo contienen barras invertidas (\d, \s, \b), que los strings de Python interpretan como secuencias de escape. Prefijar con rr'\d+' — le dice a Python que tome el string literalmente, lo que mantiene la regex en sí legible.

Aprende a programar con Coddy

COMENZAR