Guías1 caza jugable incluida

Los modificadores de las regex explicados: i, g, m, s, u, y y d

Qué cambia cada modificador de las regex en JavaScript, con ejemplos interactivos: i para ignorar mayúsculas, g global (y la trampa de lastIndex), m multilínea, s dotAll, u unicode, y sticky y d indices, además de cómo expresa Python las mismas ideas.

Logo de Regex Hunter

· 5 min de lectura

/^colou?r$/i

atrapa

  • color
  • Colour
  • COLOR
  • colour

deja libre

  • colr
  • colours
  • discolor
  • kolor

Un modificador (flag) cambia el comportamiento de todo el patrón. En JavaScript, los modificadores van después de la barra de cierre: /cat/gi. En Python son argumentos, como re.IGNORECASE, o van en línea al principio del patrón, como (?i).

JavaScript tiene siete. Dos los usarás constantemente, unos cuantos los necesitarás de vez en cuando, y uno tiene una trampa en la que ha caído casi todo el mundo. Todos los ejemplos son interactivos, así que edita los patrones y mira cómo cambian las líneas.

01i: ignorar mayúsculas

Las letras coinciden tanto en mayúscula como en minúscula:

Coincidencias5/5 como se esperaba
/^colou?r$/i

Debe coincidir3/3

  • color
  • Colour
  • COLOR

No debe2/2

  • colours
  • discolor
Pruébalo en la Zona de pruebas
Con i, el patrón coincide con cualquier mezcla de mayúsculas y minúsculas.

Te ahorra escribir [Cc][Oo][Ll]…, y también se aplica dentro de las clases: con i, [a-z] acepta también mayúsculas.

En Python: re.IGNORECASE, re.I o (?i).

02g: global

Sin g, una regex encuentra la primera coincidencia y se detiene. Con él, métodos como match, matchAll y replace trabajan con todas las coincidencias:

"a1b22c333".match(/\d+/);    // ["1"], plus index and input
"a1b22c333".match(/\d+/g);   // ["1", "22", "333"]
"a-b-c".replace(/-/, "+");   // "a+b-c"
"a-b-c".replace(/-/g, "+");  // "a+b+c"

Python no tiene g. En su lugar eliges la función: re.search encuentra una coincidencia, re.findall y re.finditer las encuentran todas, y re.sub reemplaza todas por defecto.

La trampa de lastIndex

Una regex con g (o con y) recuerda dónde terminó su última coincidencia, en lastIndex, y el siguiente test() empieza desde ahí. Si reutilizas una de esas regex con varias cadenas, los resultados empiezan a alternarse:

const hasDigit = /\d/g;

hasDigit.test("a1");  // true, lastIndex is now 2
hasDigit.test("b2");  // false: the search starts at index 2, past the "2"
hasDigit.test("b2");  // true again, lastIndex had reset to 0

La solución es sencilla: no pongas g en una regex que solo usas con test(). No lo necesitas para comprobar si algo coincide.

03m: multilínea

^ y $ coinciden al principio y al final de cada línea en lugar de solo al principio y al final de todo el texto. El artículo sobre anclas y modo multilínea lo explica a fondo.

"one\ntwo".match(/^\w+$/gm);  // ["one", "two"]

En Python: re.MULTILINE, re.M o (?m).

04s: dotAll

Normalmente, . coincide con cualquier carácter excepto un salto de línea. Con s, también coincide con los saltos de línea:

/start.*end/.test("start\nend");   // false
/start.*end/s.test("start\nend");  // true

Antes de que existiera s, la gente escribía [\s\S] para decir “cualquier carácter, sea cual sea”, y todavía lo verás en código antiguo.

En Python: re.DOTALL, re.S o (?s).

05u: unicode

u hace que el patrón trabaje con caracteres Unicode completos en lugar de con fragmentos UTF-16, y activa los escapes de propiedad como \p{L} (cualquier letra, de cualquier escritura):

Coincidencias6/6 como se esperaba
/^\p{L}+$/u

Debe coincidir4/4

  • hello
  • café
  • Zürich
  • Москва

No debe2/2

  • R2D2
  • two words
Pruébalo en la Zona de pruebas
\p{L} es una letra de cualquier alfabeto, con acentos incluidos. [a-z] rechazaría todas las líneas menos la primera.

También hace que . coincida con un emoji entero en lugar de con medio, y vuelve estricto al analizador: un escape innecesario como \- fuera de una clase pasa a ser un error de sintaxis en lugar de ignorarse sin más. El modificador v de JavaScript, más reciente, es un superconjunto más estricto de u que añade operaciones de conjuntos dentro de las clases.

El re de Python reconoce Unicode por defecto, pero no tiene \p{…}. El módulo de terceros regex lo añade.

06y: sticky

Con y, una coincidencia debe empezar exactamente en lastIndex, no en cualquier punto posterior. Sirve sobre todo para analizadores léxicos que recorren una cadena trozo a trozo:

const word = /\w+/y;

word.lastIndex = 0;
word.exec("hi there");  // ["hi"], lastIndex is now 2
word.exec("hi there");  // null: index 2 is a space, and y won't skip ahead

07d: indices

d añade a cada coincidencia un array indices con el inicio y el final de la coincidencia y de cada grupo:

const m = /(\d+)-(\d+)/d.exec("pages 12-30");

m.indices[0];  // [6, 11], the whole match
m.indices[1];  // [6, 8], the first group, "12"

Muy útil para resaltar coincidencias en un editor. Python lo trae de serie: m.span(1).

08Pruébalo

Usa el modificador i para que la solución quede corta:

Caza jugablepar 5

Atrapa yes en cualquier combinación de mayúsculas y minúsculas, y nada más.

Objetivos · 0/5 atrapados

  • yesobjetivo
  • Yesobjetivo
  • YESobjetivo
  • yEsobjetivo
  • yeSobjetivo

Inocentes · 0 errores

  • yesterdayinocente
  • eyesinocente
  • noinocente
  • yeinocente
  • y e sinocente

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

09Lista de comprobación

  • i ignora mayúsculas y minúsculas. m hace que ^ y $ funcionen por línea. s permite que . coincida con saltos de línea.
  • g encuentra todas las coincidencias, pero no lo uses con test() en una regex que reutilizas.
  • u maneja Unicode completo y activa \p{L}.
  • y solo coincide en lastIndex. d añade las posiciones de las coincidencias.
  • En Python: re.I, re.M, re.S, o en línea (?i), (?m), (?s). No hay g: usa findall o sub.

10Sigue practicando