Guías1 caza jugable incluida

Anclas en regex: ^, $ y el modo multilínea explicados

^ y $ no coinciden con caracteres, sino con posiciones. Por qué un patrón sin anclas comprueba menos de lo que crees, qué cambia el modificador m, cómo trata el $ de Python un salto de línea final y cuándo usar \A y \z en su lugar.

Logo de Regex Hunter

· 6 min de lectura

/^\d{5}$/

atrapa

  • 90210
  • 10001
  • 02139
  • 60614

deja libre

  • 9021
  • 902100
  • ZIP 90210
  • 90210-1234

La mayoría de los elementos de una regex coinciden con un carácter. Las anclas coinciden con una posición: el inicio del texto, el final, el hueco entre dos caracteres. No ocupan ningún ancho.

También son lo que más a menudo falta en un patrón de validación. Este artículo cubre ^ y $, lo que cambia el modificador m y los casos límite que varían entre lenguajes. Todos los ejemplos son interactivos, así que edita los patrones y mira cómo cambian las líneas.

01Un patrón sin anclas comprueba menos de lo que crees

Los motores de regex buscan: informan de una coincidencia si el patrón encaja en cualquier parte del texto. Así que un patrón de “código postal de cinco dígitos” sin anclas es en realidad “contiene cinco dígitos seguidos”:

Coincidencias4/4 como se esperaba
/\d{5}/
  • 90210
  • 902100
  • ZIP 90210
  • 90210-1234
Pruébalo en la Zona de pruebas
Todas las líneas coinciden. Cada una contiene cinco dígitos en algún sitio.

02^ y $

^ coincide al principio del texto y $ al final. Ponlos alrededor del patrón y la entrada entera tendrá que encajar:

Coincidencias6/6 como se esperaba
/^\d{5}$/

Debe coincidir2/2

  • 90210
  • 02139

No debe4/4

  • 9021
  • 902100
  • ZIP 90210
  • 90210-1234
Pruébalo en la Zona de pruebas
Ahora no queda sitio para nada antes ni después de los cinco dígitos.

Puedes usar solo una de las dos. ^# significa “empieza por #”, y \.pdf$ significa “termina en .pdf”:

Coincidencias4/4 como se esperaba
/\.pdf$/

Debe coincidir2/2

  • report.pdf
  • 2026 taxes.pdf

No debe2/2

  • report.pdf.exe
  • pdf-guide.txt
Pruébalo en la Zona de pruebas
Solo se fija el final del texto. El resto puede ser cualquier cosa.

03Anclas alrededor de una alternancia

| tiene la prioridad más baja de todo el patrón, más baja que las anclas. Así que ^cat|dog$ no significa “exactamente cat o dog”. Significa “empieza por cat, o termina en dog”:

Coincidencias4/4 como se esperaba
/^cat|dog$/
  • cat
  • dog
  • catalog
  • hotdog
Pruébalo en la Zona de pruebas
Las dos últimas líneas también coinciden. ^ solo se aplica a cat, y $ solo a dog.

Mete las opciones en un grupo para que las dos anclas se apliquen a ambas:

Coincidencias4/4 como se esperaba
/^(cat|dog)$/

Debe coincidir2/2

  • cat
  • dog

No debe2/2

  • catalog
  • hotdog
Pruébalo en la Zona de pruebas
El grupo hace que las anclas se apliquen a todas las alternativas.

Esta trampa aparece en código real, en listas de permitidos como ^admin|editor$ que aceptan sin avisar admin-old o not-an-editor.

04Modo multilínea

Por defecto, ^ y $ solo coinciden al principio y al final de todo el texto, aunque contenga saltos de línea. El modificador m hace que coincidan al principio y al final de cada línea:

const text = "apple\nbanana\ncherry";

text.match(/^\w+$/g);   // null: "apple\nbanana\ncherry" isn't one word
text.match(/^\w+$/gm);  // ["apple", "banana", "cherry"]

Es lo que quieres cuando extraes cosas de un archivo línea a línea. En Python es re.MULTILINE, o (?m) al principio del patrón:

import re

re.findall(r"^#+ .*$", markdown, re.MULTILINE)  # every heading line

El modificador solo cambia ^ y $. Un punto sigue sin cruzar un salto de línea. Para eso hay otro modificador, s, que se explica en el artículo sobre modificadores de las regex.

05La trampa del salto de línea final

Aquí los lenguajes difieren. En JavaScript, sin m, $ solo coincide justo al final. En Python, $ también coincide justo antes de un salto de línea situado al final del todo:

import re

re.match(r"^\d{5}$", "90210\n")    # matches in Python
re.fullmatch(r"\d{5}", "90210\n")  # None
/^\d{5}$/.test("90210\n");  // false in JavaScript

Así que en Python, ^\d{5}$ acepta un código postal con un salto de línea pegado al final. Eso puede importar si el valor va a una base de datos o a un nombre de archivo. Dos soluciones:

  • Usa re.fullmatch(), que tiene que consumir la cadena entera.
  • Usa \A y \Z: en Python, \A es el inicio absoluto y \Z el final absoluto, sin excepción para el salto de línea. (Ruby, PCRE y Java escriben ese final estricto como \z).

JavaScript no tiene \A ni \z, pero sin el modificador m sus ^ y $ ya se comportan así.

06Los límites de palabra también son anclas

\b es otra ancla de ancho cero: la posición entre un carácter de palabra y uno que no lo es. Así se busca una palabra completa dentro de un texto:

Coincidencias5/5 como se esperaba
/\bcat\b/

Debe coincidir3/3

  • the cat sat
  • cat
  • a cat.

No debe2/2

  • concatenate
  • cats
Pruébalo en la Zona de pruebas
cat sola, pero no dentro de otra palabra.

07Pruébalo

Atrapa las líneas que son un hashtag y nada más:

Caza jugablepar 6

Atrapa los hashtags: un # seguido de letras, dígitos o guiones bajos, y nada más.

Objetivos · 0/5 atrapados

  • #regexobjetivo
  • #100DaysOfCodeobjetivo
  • #aobjetivo
  • #snake_caseobjetivo
  • #2026objetivo

Inocentes · 0 errores

  • regexinocente
  • ##doubleinocente
  • #two wordsinocente
  • #inocente
  • #dash-edinocente
  • a#taginocente

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

  • Sin anclas, un patrón solo comprueba que el texto contiene una coincidencia.
  • ^ es el inicio y $ es el final. Usa los dos para validar.
  • Agrupa las alternativas dentro de las anclas: ^(cat|dog)$, no ^cat|dog$.
  • El modificador m hace que ^ y $ funcionen por línea.
  • En Python, $ admite un salto de línea final. Usa re.fullmatch() o \Z.
  • \b ancla una palabra completa.

09Sigue practicando