R

ReflexKR

Documentación de Reflex
Expresiones regulares a la vista
Lección 1

Tiempo 0:00–0:50

El pago desaparecido: buscar el texto tal cual

CASE-001

Grep & Co. Agencia de Detectives de Datos

Expediente

El pago desaparecido

Cliente

El dueño del cibercafé «Level Up»

Pruebas

El log del servidor de pagos. Un cliente asegura que pagó 4,99 dólares, pero no hay ningún registro, y está protestando.

Para cerrar el caso

Encontrar en el log las líneas con error y quedarse solo con los pagos de exactamente $4.99.

Primera mañana de trabajo. La directora deja la taza de café sobre la mesa y te acerca una hoja. «Ayer vino el dueño del cibercafé. Un cliente dice que pagó 4,99 dólares y no aparece en ningún sitio. Los logs no mienten. Búscalo».

El log es este. Hoy vas a buscar pruebas en estas cinco líneas.

2026-10-20 09:12:01 INFO  PAY user=kim  amount=$4.99  status=OK
2026-10-20 09:12:07 INFO  PAY user=lee  amount=$14.99 status=OK
2026-10-20 09:13:44 ERROR PAY user=park amount=$4.99  status=TIMEOUT
2026-10-20 09:15:02 INFO  PAY user=choi amount=$4999  status=OK
2026-10-20 09:16:30 ERROR DB  connection lost

1-1. Una regex es un «patrón de texto» (5 min)

Una expresión regular (regular expression, o regex) es un pequeño lenguaje para describir la forma del texto que quieres encontrar. En Python se usa con el módulo re. La regex más sencilla es texto sin más: el patrón ERROR encuentra el texto ERROR.

import re

log = "2026-10-20 09:13:44 ERROR PAY user=park"
m = re.search("ERROR", log)
print(m)          # <re.Match object; span=(20, 25), match='ERROR'>
  • re.search(patrón, cadena) recorre la cadena desde el principio y busca el primer sitio donde aparece el patrón.
  • Si lo encuentra, devuelve un objeto Match; si no, devuelve None.

Laboratorio de pruebas

re.search(r"", text)

Valor devuelto

Cambia entre search y findall. search encuentra solo la primera coincidencia; findall, todas.

1-2. Si lo encontró y dónde: el objeto Match (5 min)

El objeto Match es la prueba de que «se encontró algo» y, a la vez, un informe que dice qué se encontró y dónde.

m = re.search("ERROR", log)
if m:                 # verdadero si encontró algo; None es falso
    print(m.group())  # ERROR       (el texto encontrado)
    print(m.span())   # (20, 25)    (posición inicial, posición final)
  • Se comprueba directamente como verdadero o falso, con if m:. Si no encontró nada, m es None, y llamar a m.group() lanza un AttributeError.
  • La posición final de span() no se incluye. Es la misma regla por la que log[20:25] es "ERROR".
  • En el Laboratorio de pruebas, la casilla «Primera coincidencia» muestra justo estos valores.

1-3. Los 14 caracteres especiales (10 min)

Casi todos los caracteres se encuentran a sí mismos. Pero estos 14 son metacaracteres: en una regex tienen un significado especial.

.  ^  $  *  +  ?  {  }  [  ]  \  |  (  )

Hoy solo veremos el primero, ., que significa un carácter cualquiera, menos el salto de línea. Los demás irán saliendo, uno por lección.

re.search("a.c", "abc")    # coincide: la b ocupa el lugar del .
re.search("a.c", "a-c")    # coincide: el - también es un carácter cualquiera
re.search("a.c", "ac")     # None: el . siempre ocupa exactamente un carácter
re.search("a.c", "a\nc")   # None: el salto de línea no cuenta para el .

El consejo de Dot

Yo me subo a cualquier sitio de la agencia: mesas, sillas, hasta el teclado de la directora. Solo hay una cosa que no puedo cruzar: la ventana (el salto de línea). Por eso me llamo Dot (.). Dicen que, si algún día alguien me abre la ventana, podré pasar al otro lado.

Laboratorio de pruebas

re.search(r"", text)

Valor devuelto

a.c solo coincide cuando entre la a y la c hay exactamente un carácter.

1-4. Apagar el significado especial con la barra invertida (10 min)

Volvamos al caso. Supongamos que las cinco líneas del log de arriba están en una cadena llamada pay_log. Si escribes 4.99 para buscar los pagos de 4,99 dólares, ¿qué pasa?

re.findall("4.99", pay_log)   # ['4.99', '4.99', '4.99', '4999']  ← ¿cuatro?

Deberían salir dos resultados y salen cuatro. Se ha colado el final de $14.99, que también es 4.99, y como . significa «un carácter cualquiera», ha entrado incluso el 4999 de $4999. Para buscar un metacarácter tal cual, se le pone delante una barra invertida \. \. es un punto de verdad.

$ también es un metacarácter. Su significado lo veremos en la lección 4; por ahora, recuerda solo que «escrito tal cual, no busca el signo del dólar». Así que la respuesta correcta es \$4\.99.

re.findall(r"\$4\.99", pay_log)   # ['$4.99', '$4.99']

Laboratorio de pruebas

re.search(r"", text)

Valor devuelto

Empieza por 4.99 y añade \. y luego \$. Lo tienes cuando todas las condiciones del caso se pongan en verde.

1-5. ¿Por qué r"..."? Las cadenas raw (5 min)

Arriba escribimos r"\$4\.99", con una r delante de las comillas. Esto se llama cadena raw (cadena «en bruto»).

La barra invertida también es especial en las cadenas de Python: "\n" es un salto de línea y "\t", un tabulador. Por eso, si escribes una regex en una cadena normal, Python interpreta primero las barras invertidas y re recibe un patrón que no es el que querías.

print(len("\b"))    # 1  ← Python ha convertido \b en un solo carácter, el «retroceso»
print(len(r"\b"))   # 2  ← la barra invertida y la b, dos caracteres tal cual
  • r"..." le pasa las barras invertidas a re sin tocarlas. Las regex se escriben siempre como cadenas raw.
  • Desde Python 3.12, si en una cadena normal pones un escape que Python no conoce, como "\d", salta un SyntaxWarning. Con una cadena raw no hay aviso.

1-6. Buscar tal cual lo que escribió el cliente: re.escape (5 min)

El dueño del cibercafé te pide: «El usuario del cliente es kim.99+, búscame eso también». Si escribes ese texto directamente como patrón, . y + se interpretan como metacaracteres. Cuando quieras buscar tal cual algo que ha escrito una persona, re.escape pone la barra invertida delante de cada metacarácter por ti.

print(re.escape("kim.99+"))                        # kim\.99\+
re.search(re.escape("kim.99+"), "user=kim.99+")    # coincide

Caso resuelto (10 min)

En resumen: las líneas con error se encuentran con ERROR, y los pagos de exactamente 4,99 dólares, con \$4\.99. Si juntas las dos condiciones, queda al descubierto que el pago del cliente park falló con un error TIMEOUT y nunca quedó registrado.

for line in pay_log.splitlines():
    if re.search("ERROR", line) and re.search(r"\$4\.99", line):
        print(line)
# 2026-10-20 09:13:44 ERROR PAY user=park amount=$4.99  status=TIMEOUT

Informe de caso cerrado — A las 09:13:44 el servidor de pagos dio el pago por fallido por tiempo de espera agotado, pero en la pantalla del cliente aparecía como completado. Se recomienda al dueño del cibercafé que haga el reembolso.

Ejercicios

  1. Busca en el log todas las líneas con INFO. ¿Cuántas hay?
  2. ¿Qué encuentra \$1.\.99? Intenta adivinarlo antes de comprobarlo en el laboratorio.
  3. Adivina qué devuelve re.escape("1+1=2? [yes]") y luego ejecútalo.

La libreta de la directora

  • Casi todos los caracteres se encuentran a sí mismos. Solo son especiales los 14 metacaracteres . ^ $ * + ? { } [ ] \ | ( )

  • . es un carácter cualquiera menos el salto de línea. Un punto de verdad es \.

  • re.search devuelve un Match o None. Se comprueba con if m: y se mira con m.group() y m.span().

  • Las regex, siempre como cadenas raw r"...".

  • Para buscar tal cual lo que escribe una persona, re.escape.

← Anterior

Resumen del curso

Siguiente →

Lección 2 · El coche que se dio a la fuga: clases de caracteres

Recibe avisos de nuevas lecciones

Te avisaremos por correo cuando este curso tenga lecciones nuevas o se abra un curso de continuación.

Datos: tu correo electrónico · Finalidad: avisos de nuevas lecciones o de la publicación de este curso · Conservación: hasta que pidas que lo borremos. No lo usamos para nada más ni lo compartimos. Responde a cualquier aviso y lo borraremos enseguida.

Preguntas y respuestas

Pregunta lo que quieras sobre esta lección. Aquí se reúnen las preguntas de todas las versiones de idioma de esta página.

Se muestra como texto plano, sin enlaces ni formato.

R

ReflexKR

Aprende Python y Reflex haciendo. Todos los ejemplos se ejecutaron y verificaron en Reflex 0.10.0.

ReflexKR es gratis y sin banners publicitarios. Si te ayudó, puedes apoyarlo con un café. ☕ Invítanos un café

Aviso de afiliados
한국어English日本語简体中文EspañolDeutsch

© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0

Built with Reflex