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.

· 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:
/^colou?r$/iDebe coincidir3/3
- color
- Colour
- COLOR
No debe2/2
- colours
- discolor
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):
/^\p{L}+$/uDebe coincidir4/4
- hello
- café
- Zürich
- Москва
No debe2/2
- R2D2
- two words
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:
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.
09Lista de comprobación
iignora mayúsculas y minúsculas.mhace que^y$funcionen por línea.spermite que.coincida con saltos de línea.gencuentra todas las coincidencias, pero no lo uses contest()en una regex que reutilizas.umaneja Unicode completo y activa\p{L}.ysolo coincide enlastIndex.dañade las posiciones de las coincidencias.- En Python:
re.I,re.M,re.S, o en línea(?i),(?m),(?s). No hayg: usafindallosub.
10Sigue practicando
- La sección de modificadores de la guía tiene una referencia rápida, y unicode profundiza en
u. - Domando líneas es un pack de práctica donde los modificadores importan.
- Prueba la caza de hoy, o repasa tableros anteriores en el archivo.