regex-grupos-de-captura

Grupos de captura en Regex

Los grupos de captura en Regex son una herramienta que nos permite identificar y extraer partes específicas de una cadena de texto.

Para definir un grupo de captura en Regex, simplemente tenemos que delimitar una porción una expresión regular que por paréntesis ( ).

Este grupo permite capturar la coincidencia del patrón delimitado. Es decir, que además de hacer coincidir partes del texto, podemos almacenar esas coincidencias y reutilizarlas más adelante en la expresión o en el código.

Sintaxis básica de los grupos de captura

El uso básico de los grupos de captura implica delimitar los patrones con paréntesis. A partir de ahí, podemos extraer los valores capturados para utilizarlos en posteriores operaciones.

La sintaxis de un grupo de captura es simplemente envolver el patrón en paréntesis:

(pattern)

Donde pattern es cualquier secuencia de caracteres que queremos capturar. Estos grupos se numeran de manera automática, comenzando desde 1. El número 0 siempre se refiere a la coincidencia completa de la expresión regular.

Ejemplos de grupo de captura

Vamos a verlo mejor si lo vemos con unos ejemplos

(\d{3})-(\d{2})-(\d{4})

Esta expresión regular captura un formato de número de teléfono simplificado, donde:

  • (\d{3}) captura los primeros tres dígitos.
  • (\d{2}) captura los siguientes dos dígitos.
  • (\d{4}) captura los últimos cuatro dígitos.

Otro ejemplo, supongamos que tenemos este patrón, que captura dos palabras separadas por espacios.

(\w+)\s+(\w+)

La secuencia (\w+) captura cualquier grupo de caracteres alfanuméricos, y \s+ coincide con uno o más espacios en blanco.

Si aplicamos la expresión al siguiente texto:

Hola Mundo

Las capturas resultantes serían:

  • Grupo 1: Hola
  • Grupo 2: Mundo

Cuantificadores aplicados a grupos

Una de las ventajas de usar grupos es que podemos aplicar cuantificadores a todo el grupo en lugar de solo a un carácter individual. Esto nos permite definir de manera más precisa las repeticiones de secuencias completas.

(\d{2}-){3}

Este patrón captura una secuencia de dos dígitos seguida por un guion, y requiere que dicha secuencia se repita exactamente tres veces. Es equivalente a:

\d{2}-\d{2}-\d{2}-

Pero mucho más limpio y fácil de leer.

Referencias a grupos de captura

Una de las características más útiles de los grupos de captura es la posibilidad de referirse a ellos dentro de la misma expresión o en operaciones posteriores. Esto se puede hacer de varias maneras, dependiendo del contexto en el que estemos utilizando la expresión regular.

Referencias en la misma expresión: Backreferences

Las backreferences permiten utilizar un grupo capturado más adelante en la misma expresión. Esto es útil cuando queremos encontrar partes del texto que se repiten.

(\w+)\s+\1

En esta expresión, \1 se refiere al primer grupo capturado (\w+). Esto significa que el patrón buscará una palabra seguida por un espacio y la misma palabra repetida inmediatamente después.

Aplicado a este texto:

hola hola mundo

El grupo de captura se activa en la secuencia "hola hola", ya que la palabra "hola" aparece dos veces consecutivas.

Referencias en reemplazos

Cuando trabajamos con funciones de reemplazo en lenguajes de programación, los grupos de captura nos permiten acceder a las coincidencias capturadas y utilizarlas para formar nuevas cadenas. En la mayoría de los lenguajes, estas coincidencias se numeran de manera secuencial.

Por ejemplo, en JavaScript, podemos usar grupos de captura dentro de la función replace:

let texto = "2024-09-27";
let nuevoTexto = texto.replace(/(\d{4})-(\d{2})-(\d{2})/, "$3/$2/$1");
console.log(nuevoTexto); // "27/09/2024"

Aquí, el patrón (\d{4})-(\d{2})-(\d{2}) captura el formato de fecha "2024-09-27", y el método replace lo reordena en formato "día/mes/año" usando las referencias $1, $2 y $3.

Grupos no capturantes

En algunos casos, no necesitamos capturar la coincidencia de un grupo, sino simplemente utilizar los paréntesis para agrupar partes del patrón. Para estos casos, podemos usar grupos no capturantes, que se definen usando la sintaxis (?:pattern).

Ejemplo de grupo no capturante:

(?:\d{3})-\d{2}-\d{4}

Aquí, el primer conjunto de tres dígitos (?:\d{3}) no se capturará, pero sigue siendo parte de la expresión.

Nombres en grupos de captura

En expresiones regulares más avanzadas, es posible utilizar grupos de captura con nombre para mejorar la legibilidad y manejar patrones más complejos. En lugar de referirnos a un grupo por su número, podemos asignarle un nombre y referirnos a él de manera explícita.

La sintaxis para los grupos con nombre varía según el lenguaje, pero en muchos casos es así:

(?<nombreGrupo>pattern)

Por ejemplo:

(?<nombre>\w+)\s(?<apellido>\w+)

En este caso, podemos capturar dos palabras, asignando al primer grupo el nombre "nombre" y al segundo el nombre "apellido". Esto es útil en lenguajes como Python, donde podemos acceder a las capturas de esta manera:

import re

texto = "Luis Perez"
patron = r"(?P<nombre>\w+)\s(?P<apellido>\w+)"
match = re.search(patron, texto)
print(match.group("nombre"))  # Luis
print(match.group("apellido"))  # Perez