Guías1 caza jugable incluida

Grupos con nombre y grupos sin captura en regex

Los paréntesis hacen dos trabajos: agrupan y capturan. Cómo los grupos sin captura (?:…) agrupan sin capturar, cómo los grupos con nombre (?<year>…) hacen legibles las capturas, cómo volver a ellos con \k<name> y cómo lo escribe Python.

Logo de Regex Hunter

· 5 min de lectura

/^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/

atrapa

  • 2026-10-13
  • 1999-12-31
  • 2000-01-01
  • 2026-02-28

deja libre

  • 26-10-13
  • 2026/10/13
  • 2026-1-3
  • 13-10-2026

Los paréntesis de una regex hacen dos trabajos a la vez. Agrupan, para que un cuantificador o un | se aplique a todo lo que hay dentro. Y capturan, guardando el texto con el que coincidieron para que puedas usarlo después.

A menudo solo quieres uno de los dos. Este artículo cubre los dos tipos de grupo que separan esos trabajos: los grupos sin captura y los grupos con nombre. Todos los ejemplos son interactivos, así que edita los patrones y mira cómo cambian las líneas.

01Los grupos normales capturan

Un grupo normal guarda lo que encontró, numerado desde 1 según la posición de su paréntesis de apertura:

const m = "2026-10-13".match(/(\d{4})-(\d{2})-(\d{2})/);

m[0];  // "2026-10-13", the whole match
m[1];  // "2026"
m[2];  // "10"
m[3];  // "13"

Eso funciona hasta que cambia el patrón. Añade un grupo cerca del principio y todos los números que vienen detrás se desplazan, y m[2] pasa a ser otra cosa sin avisar.

02Grupos sin captura: (?:…)

Escribe (?: en lugar de ( cuando necesites agrupar pero no te importe el texto. Aquí el grupo solo existe para que + repita “palabra y luego un espacio”:

Coincidencias4/4 como se esperaba
/^(?:\w+ )+\w+$/

Debe coincidir2/2

  • two words
  • one two three

No debe2/2

  • single
  • double space
Pruébalo en la Zona de pruebas
(?: … ) agrupa “una palabra y un espacio” para que + pueda repetirlo. No se captura nada.

Coincide exactamente igual que (\w+ )+\w+. La diferencia está solo en lo que recibes: ninguna captura que numerar y nada que se desplace cuando editas el patrón. Además es un poco más barato, porque el motor no guarda el texto.

Un buen hábito: usa (?:…) para cada grupo que no vayas a leer después. Así, los grupos numerados o con nombre que queden serán los que significan algo.

03Grupos con nombre: (?…)

Ponle un nombre a un grupo y léelo por su nombre en lugar de por su número:

Coincidencias5/5 como se esperaba
/^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/

Debe coincidir2/2

  • 2026-10-13
  • 1999-12-31

No debe3/3

  • 26-10-13
  • 2026/10/13
  • 2026-1-3
Pruébalo en la Zona de pruebas
El mismo patrón de fecha, ahora con un nombre para cada parte. Coincide con las mismas líneas que la versión numerada.
const { year, month, day } =
  "2026-10-13".match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/).groups;

year;  // "2026"

Los grupos con nombre siguen teniendo número, así que m[1] es el año en ambos casos. Los nombres solo hacen que el código sobreviva a los cambios en el patrón.

También funcionan en los reemplazos, con $<name>:

"2026-10-13".replace(
  /(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})/,
  "$<d>/$<m>/$<y>",
);  // "13/10/2026"

04Hacer referencia a un grupo: \k

Una referencia inversa (backreference) coincide con el mismo texto con el que coincidió antes un grupo. Con grupos con nombre, se escribe \k<name> en lugar de \1:

Coincidencias4/4 como se esperaba
/^(?<quote>["']).*\k<quote>$/

Debe coincidir2/2

  • "hello"
  • 'hello'

No debe2/2

  • "hello'
  • 'hello"
Pruébalo en la Zona de pruebas
La comilla de cierre tiene que ser el mismo carácter que la de apertura.

Así el patrón dice lo que significa, algo que \1 nunca consigue, y sigue funcionando si añades grupos delante.

05Python lo escribe de otra manera

Python tuvo grupos con nombre antes que nadie, con una P:

import re

m = re.match(r"(?P<year>\d{4})-(?P<month>\d{2})", "2026-10")
m.group("year")      # "2026"
m.groupdict()        # {"year": "2026", "month": "10"}

re.sub(r"(?P<y>\d{4})-(?P<m>\d{2})", r"\g<m>/\g<y>", "2026-10")  # "10/2026"
re.match(r"(?P<q>[\"']).*(?P=q)$", '"hi"')  # backreference by name

Así que la misma idea es (?<name>…) y \k<name> en JavaScript, pero (?P<name>…), (?P=name) y \g<name> en Python. El grupo sin captura (?:…) es igual en todas partes.

06Grupos que no capturan cada repetición

Una sorpresa más: un grupo dentro de un cuantificador solo conserva su última repetición.

"abc".match(/(\w)+/)[1];  // "c", not ["a", "b", "c"]

Si necesitas cada repetición, usa el modificador g con matchAll (o re.findall) sobre el patrón interior.

07Pruébalo

Las comillas tienen que coincidir. Usa un grupo y una referencia que vuelva a él:

Caza jugablepar 12

Atrapa el texto entre comillas que se correspondan: "…" o '…'.

Objetivos · 0/5 atrapados

  • "hi"objetivo
  • 'hi'objetivo
  • "it's"objetivo
  • 'say "no"'objetivo
  • ""objetivo

Inocentes · 0 errores

  • "hi'inocente
  • 'hi"inocente
  • hiinocente
  • "hiinocente
  • hi"inocente

Escribe una regex: el tablero se actualiza mientras escribes.

Pruébalo en la Zona de pruebas
¿Te gustó? Cada día llega una nueva.Jugar la caza de hoy

08Lista de comprobación

  • ( … ) agrupa y captura. (?: … ) solo agrupa.
  • Usa (?: … ) para cada grupo que no vayas a leer.
  • (?<name> … ) captura con nombre. Léelo con .groups.name y reemplaza con $<name>.
  • \k<name> vuelve a coincidir con el mismo texto.
  • En Python: (?P<name> … ), (?P=name) y \g<name>.
  • Un grupo repetido solo conserva su última repetición.

09Sigue practicando