Expresiones regulares (regexp) en JavaScript

Descubrí qué son y para qué sirven las Expresiones Regulares en JavaScript, poderosas herramientas para la manipulación de texto. Aprendé sus características clave y dominá ejemplos prácticos para validar, buscar y reemplazar patrones complejos de manera eficiente en tu código.

expresiones reguales regex javascript

1. ¿Qué son las expresiones regulares regexp en JavaScript?

Las Expresiones Regulares son, en esencia, secuencias de caracteres que forman un patrón de búsqueda. Piensa en ellas como un lenguaje de mini-programación o un sistema de notación especializado que te permite describir patrones de texto de una manera muy concisa y potente.

🎯Propósito principal:

El propósito fundamental de las expresiones regulares es encontrar, manipular y validar texto basándose en esos patrones. Son increíblemente útiles para tareas como:

  1. Búsqueda de patrones: Encontrar una o varias ocurrencias de un patrón específico dentro de una cadena de texto.
    • Ejemplo: ¿Hay una dirección de correo electrónico en este texto? ¿Dónde está?
    • Ejemplo: Encuentra todas las palabras que comienzan con «pre» y terminan con «ión».
  2. Validación de datos: Verificar si una cadena de texto cumple con un formato o estructura determinada.
    • Ejemplo: ¿Es esta una fecha válida (DD/MM/AAAA)?
    • Ejemplo: ¿El número de teléfono ingresado tiene el formato correcto (ej. XXX-XXX-XXXX)?
    • Ejemplo: ¿La contraseña cumple con los requisitos de seguridad (al menos 8 caracteres, una mayúscula, un número, un símbolo)?
  3. Reemplazo de texto: Sustituir partes de una cadena que coincidan con un patrón por otro texto.
    • Ejemplo: Reemplazar todos los espacios múltiples por un solo espacio.
    • Ejemplo: Estandarizar formatos de fecha de «DD-MM-AAAA» a «AAAA/MM/DD».
    • Ejemplo: Eliminar caracteres especiales no deseados de una entrada de usuario.
  4. Extracción de información (Parsing): Aislar partes específicas de una cadena que siguen un patrón.
    • Ejemplo: Extraer el nombre de usuario y el dominio de una dirección de correo electrónico.
    • Ejemplo: Obtener todos los números de un documento.

1.1. Ejemplo de usos de una regexp:

Validación de Formularios (¡El Uso Más Común y Crucial!)

Supongamos que tenemos cualquier página con formularios HTML de entrada de usuario, tales como:

  • Formularios de registro/login
  • Formularios de contacto
  • Checkouts de e-commerce
  • Páginas de perfil de usuario
  • Paneles de administración con campos de entrada

AHORA BIEN….Cuando un usuario ingresa datos, necesitas asegurarte de que tengan el formato correcto antes de enviarlos al servidor (validación del lado del cliente). Esto mejora la experiencia del usuario al darle retroalimentación inmediata y reduce la carga del servidor. Aquí es donde usamos una expresión regular para asegurarnos

📌EMAIL:^\S+@\S+\.\S+$ (este es un patrón (regexp) básico para email, aunque los emails son muy complejos). Más adelante iremos explicando donde se usan estos patrones

  • ¿Por qué RegEx? Para asegurar que el email tenga un @ y un ., y que no haya espacios. Si el usuario ingresa «juan@ejemplo», la RegEx lo validaría como correcto. Si ingresa «juan@ejemplo», «juan», o «[email protected]@», la RegEx lo detectaría como incorrecto.

📌CONTRASEÑAS:^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$ (al menos una minúscula, una mayúscula, un dígito, un símbolo y 8 caracteres).

  • ¿Por qué RegEx? Para aplicar múltiples reglas de seguridad en un solo patrón, forzando al usuario a crear contraseñas robustas. Sin RegEx, requeriría múltiples y complejos condicionales if/else anidados o funciones auxiliares.

📌NÚMEROS DE TELÉFONO:^\+?\d{1,3}[- ]?\d{3}[- ]?\d{4,10}$ (ejemplo para un formato flexible).

  • ¿Por qué RegEx? Para permitir diferentes formatos de entrada (con o sin guiones, con código de país opcional) y asegurar que solo sean dígitos.

📌CÓDIGOS POSTALES, FECHAS (DD/MM/AAAA), URLs,: Cada uno con su propio patrón.

  • ¿Por qué RegEx? Para estandarizar y verificar el formato de entrada, crucial para el procesamiento de datos posterior y la prevención de errores.

2. ¿Cómo crear una expresión regular en JavaScript?

Hay dos formas principales de hacerlo, y la que elijas depende de si tu patrón de búsqueda es fijo o si necesitas construirlo de forma dinámica.

2.1. Usando la sintaxis literal (la forma más común y recomendada)

Esta es la manera más directa de crear una expresión regular cuando ya sabés cuál va a ser tu patrón de búsqueda al momento de escribir el código.

SINTAXIS:

/patron/banderas
  • / (Barras diagonales): Estas actúan como delimitadores. Todo lo que esté entre ellas es tu patrón de búsqueda.
  • patron: Acá va la secuencia de caracteres que describe lo que queremos encontrar (pueden ser letras, números, metacaracteres como \d para dígitos, . para cualquier carácter, cuantificadores, anclas, grupos, alternancia, etc.) Iremos ampliando
  • banderas (opcional): También conocidas como flags o modificadores, son letras sueltas que modifican cómo se comporta la búsqueda (punto 4 ampliamos) . Las más comunes son:
    • g (global): Para encontrar todas las coincidencias en lugar de solo la primera.
    • i (insensitive): Para que la búsqueda ignore mayúsculas y minúsculas.
    • m (multiline): Para que ^ y $ coincidan con el inicio/fin de cada línea, no solo de la cadena completa.

EJEMPLOS:

// Una RegEx simple para buscar la palabra "hola"
const regexHola = /hola/;

// Una RegEx para buscar la palabra "JavaScript" sin importar mayúsculas/minúsculas
const regexJS = /javascript/i;

// Una RegEx para encontrar todos los números en una cadena
const regexNumeros = /\d+/g; // El '+' significa "uno o más dígitos"
Lenguaje del código: JavaScript (javascript)

¿CUÁNDO USARLA?: Ideal para la mayoría de los casos donde el patrón es constante y lo conocés de antemano. Es más legible y, en general, un poco más eficiente.

EJEMPLO CONCRETO:

Supongamos que tenemos el siguiente texto:

let texto = "Hoy es domingo. Mañana será lunes. El fin de semana es sábado y domingo.";Lenguaje del código: JavaScript (javascript)

Queremos buscar todas las veces que aparece la palabra «domingo», sin importar si está en mayúsculas o minúsculas.

Usamos la expresión regular literal:

// 1. Creo la expresión regular con sintaxis literal
let regex = /domingo/gi;

// 2. Uso match() para encontrar todas las coincidencias
let resultado = texto.match(regex);

// 3. Muestro el resultado
console.log(resultado); // ["domingo", "domingo"]Lenguaje del código: JavaScript (javascript)

Explicación del código:

  • /domingo/gi → es la expresión regular:
    • domingo → el patrón que buscamos.
    • g → modificador global: busca todas las coincidencias, no solo la primera.
    • i → ignorar mayúsculas/minúsculas: si el texto tuviera «Domingo» o «DOMINGO», igual las encontraría.
  • texto.match(regex) → devuelve un array con todas las palabras encontradas.

2.2. Usando el constructor RegExp (para patrones dinámicos)

Usas esta forma cuando necesitas construir el patrón de búsqueda a partir de una variable JS o alguna lógica en tiempo de ejecución.

🤔¿Qué significa variable o lógica en tiempo de ejecución?

Básicamente, significa que debemos crear un patrón de búsqueda o validación sobre unos datos que, por ejemplo, un usuario ingresará en un formulario, siguiendo dicha lógica:

  1. Definir la «regla» o «plantilla» del patrón de búsqueda/validación que esperas, basándote en la lógica de tu programa. Sabes qué tipo de dato esperas (un email, un número, una fecha con cierto formato, etc.), pero no sabes cuál será el valor exacto que el usuario introducirá.
  2. Construir dinámicamente ese patrón (la expresión regular) en el momento en que tu código necesita procesar la entrada del usuario. Esto es porque el contenido específico de ese patrón (ej. si el patrón debe incluir «nombreUsuario» o «codigoPostal») puede depender de algo que solo se sabe en tiempo de ejecución (como una preferencia del usuario, datos de una API, o el valor de otra variable).
  3. Luego, aplicar ese patrón creado dinámicamente al dato real que el usuario ingresó.

SINTAXIS:

new RegExp("patron", "banderas")Lenguaje del código: JavaScript (javascript)
  • new RegExp(...): Estás creando una nueva instancia del objeto RegExp.
  • "patron_como_cadena": El primer argumento es una cadena de texto que contiene tu patrón (pueden ser caracteres literales, metacaracteres, cuantificadores, anclas, grupos, alternancia, etc.).
  • "banderas_como_cadena" (opcional): El segundo argumento es otra cadena de texto con las banderas que quieras aplicar (ej. "gi" para global e insensible).

NOTA! Cuando colocamos el patrón y la bandera los debemos colocar como si fueran un string (poniéndolo entre comillas)

EJEMPLOS:

// Si el usuario introduce lo que quiere buscar
const terminoBusqueda = prompt("¿Qué palabra quieres buscar?");
const regexDinamica = new RegExp(terminoBusqueda, "gi"); // Busca lo que el usuario escribió, globalmente y sin distinguir mayúsculas/minúsculas

// Un ejemplo importante: ¡El escape de la barra invertida!
// Si quiero buscar un dígito (\d)
const regexDigitoLiteral = /\d/; // Con sintaxis literal
const regexDigitoDinamico = new RegExp("\\d"); // Con constructor, la '\' se escapa con otra '\'


Lenguaje del código: JavaScript (javascript)

¿CUÁNDO USARLO?: Cuando el patrón de tu expresión regular (o incluso las banderas) necesita cambiar en función de la entrada del usuario, los datos que recibís, o cualquier otra lógica de tu programa.

EJEMPLO CONCRETO:

Supongamos que tenemos un texto preestablecido en nuestra página web y queremos permitir que, a través de un input, un usuario introduzca una palabra.

Luego, verificamos si esa palabra se encuentra dentro del texto. Para realizar esta búsqueda de manera flexible e ignorando mayúsculas/minúsculas, usamos el constructor RegExp, ya que el patrón de búsqueda será dinámico según lo que escriba el usuario.

Código del ejemplo:

// 1.  Tenemos un texto predefinido en la web, por ejemplo
 let texto = "Hoy es domingo. Mañana será lunes. El fin de semana es sábado y DOMINGO.";

// 2. Pido al usuario una palabra
let palabraDelUsuario = prompt("¿Qué palabra querés buscar?");

// 3. Creo el RegExp dinámico
let regex = new RegExp(palabraDelUsuario, "gi");

// 4. Busco la palabra
let resultado = texto.match(regex);

// 5. Muestro el resultado
console.log(resultado);Lenguaje del código: JavaScript (javascript)

Explicación:

  1. Tenemos un texto predefinido en la web
    • ➡ Este texto podría ser el contenido de tu página web (por ejemplo, dentro de un <p>), o una variable con cualquier texto que quieras analizar.
  2. Le pedimos al usuario que escriba una palabra
    • ➡ El prompt() es una manera de pedirle al usuario que escriba un dato, y ese dato queda guardado en la variable palabraDelUsuario.
    • ➡ El usuario podría escribir por ejemplo:
      • domingo
      • lunes
      • fin
      • cualquier otra cosa.
  3. Creamos la expresión regular DINÁMICAMENTE: let regex = new RegExp(palabraDelUsuario, "gi");
    • ➡ Lo que hacemos acá es transformar la palabra del usuario en un patrón de búsqueda (expresión regular).
    • ➡ Le ponemos "gi" para que:
      • g: busque todas las veces que aparezca la palabra.
      • i: no distinga entre mayúsculas y minúsculas (así encuentra "domingo", "Domingo", "DOMINGO", etc.).
  4. Buscamos en el texto si está esa palabra
    • .match(regex) aplica la expresión regular al texto y devuelve:
      • Un array de JS con todas las coincidencias encontradas, o
      • null si no encontró nada.
  5. Mostramos el resultado
    • ➡ Si el usuario escribió domingo, la consola mostraría:
    • ➡ Si el usuario escribió lunes, la consola mostraría:
    • ➡ Si el usuario escribió algo que no está (por ejemplo "martes"), la consola mostraría:

RECUERDA!!! La diferencia CRÍTICA entre crear expresiones regulares de manera literal y usando el constructor radica en cómo manejas la barra invertida (\) para los metacaracteres:

Dado que el patrón se pasa como una cadena de texto, cualquier barra invertida (\) que sea parte de un metacaracter de la RegEx (como \d, \s, \., \b) debe ser escapada con otra barra invertida. Es decir, \d se convierte en "\\d", y \. se convierte en "\\.". Esto es porque la primera barra invertida escapa a la segunda para que JavaScript la interprete como una barra invertida literal dentro de la cadena, y luego esa segunda barra invertida es la que la RegEx usa para su metacaracter.

Veamos las diferencias con ejemplos:

ConceptoSintaxis Literal (/patron/)Constructor new RegExp("patron_como_cadena")Explicación
Dígito (\d)/\d/new RegExp("\\d")En literal, \d se entiende directamente. En constructor, \\ es para que JavaScript vea \ como parte de la cadena, no como escape de string.
Espacio (\s)/\s/new RegExp("\\s")Lo mismo que el dígito.
Punto literal (.)/\./new RegExp("\\."). es un metacaracter (cualquier char). Para buscar un punto real, hay que escaparlo. En literal, un solo \ basta.
Barra invertida (\)/\\/new RegExp("\\\\")Para buscar una barra invertida literal. En literal, \\ la escapa. En constructor, se escapa doblemente en la cadena, resultando en \\\\.
Inicio de línea (^)/^abc/new RegExp("^abc")Igual en ambos, no usa \
Grupo de captura/(abc)/new RegExp("(abc)")Igual en ambos, no usa \
Cuantificador/a+/new RegExp("a+")Igual en ambos, no usa \

Resumen entre literal y constructor:

Sintaxis Literal (/patron/banderas):

  • Ventaja: Más limpia y fácil de leer, especialmente con metacaracteres que usan \. No necesitas preocuparte por el doble escape.
  • Limitación: El patrón es fijo y no puede ser construido dinámicamente usando variables de JavaScript directamente dentro de las barras /.../.

Constructor new RegExp("patron_como_cadena", "banderas_como_cadena"):

  • Ventaja: Te permite construir el patrón de búsqueda dinámicamente utilizando variables o la lógica de tu programa.
  • Limitación: Requiere que escapes doblemente las barras invertidas (\\) cuando quieras usar un metacaracter que las contenga (como \d, \s, \., \b). Esto se debe a que la cadena de JavaScript procesa el escape primero.

Ambas formas te permiten crear expresiones regulares con la misma funcionalidad subyacente. La elección depende de si tu patrón es estático o necesita ser generado en tiempo de ejecución.

3. ¿Cómo usar las expresiones regulares? Módulos

El proceso general de usar una expresión regular implica tres pasos principales:

  1. Crear la expresión regular: Definir tu patrón de búsqueda.
  2. Preparar la cadena de texto: Tener el texto donde vas a buscar o validar.
  3. Aplicar métodos: Usar los métodos de JavaScript para ejecutar la búsqueda, validación o manipulación.

Paso 1: Crear la expresión regular

Como ya vimos, tenés dos formas:

OPCIÓN A: Sintaxis Literal (punto 2.1.)

let regex = /patron/modificadores;Lenguaje del código: JavaScript (javascript)

OPCIÓN B: Constructor RegExp (punto 2.2.)

let regex = new RegExp("patron", "modificadores");Lenguaje del código: JavaScript (javascript)

Paso 2: Preparar la cadena de texto (donde buscarás o validarás)

Necesitas tener la string (cadena de texto) sobre la cual vas a aplicar tu expresión regular.

// Ejemplo 1: Una frase para buscar
const fraseEjemplo = "El gato es un animal ágil. Mi gato duerme mucho.";

// Ejemplo 2: Un email ingresado por un usuario
const emailUsuario = "[email protected]";

// Ejemplo 3: Un posible ID de cupón
const idCupon = "A12345E";
Lenguaje del código: JavaScript (javascript)

Paso 3: Aplicar métodos para usar la expresión regular

Aquí es donde entra en juego la acción. Las expresiones regulares se utilizan con métodos específicos que pertenecen tanto al objeto RegExp (la expresión regular que creaste) como al objeto String (la cadena de texto donde vas a trabajar).

A. Métodos del Objeto RegExp:

✅MÉTODO test: regex.test(string):

Es el método más simple y común para validar. Devuelve true si la expresión regular encuentra al menos una coincidencia en la cadena, y false si no encuentra ninguna.

Cuándo usarlo: Principalmente para validación de formatos (emails, contraseñas, etc.) o para verificar la presencia de un patrón

const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; // Expresión para email
const emailValido = "[email protected]";
const emailInvalido = "prueba@dominio";

console.log(emailRegex.test(emailValido));    // Salida: true
console.log(emailRegex.test(emailInvalido));  // Salida: falseLenguaje del código: JavaScript (javascript)

.test() devuelve true si todo el texto cumple el formato de email según la expresión regular. En este caso:

  • El segundo no tiene .com, así que falla → false
  • El primer email es válido → true

NOTA!!!! Si te animas y deseas ver el resultado de este ejemplo y de todos los que iremos proporcionando directamente desde tu PC, te invito a seguir estos pasos.

  1. Primero, revisa el punto 5 del siguiente artículo sobre como usar e instalar VSCode (este es el editor de código mas usado), donde encontrarás los pasos para crear la estructura necesaria para visualizar una página desde tu navegador predeterminado.
  2. Si entendiste correctamente este paso anterior, sabrás donde colocar el código script que te acabamos de proporcionar (arriba). Ahora, puedes visualizar el resultado, para ello puedes hacer lo siguiente:
    • Una vez abierta y visualizada la página, abre la consola del navegador presionando la tecla F12.
    • Ahora, dirígete a la pestaña que dice Console, y desde aquí podrás ver el resultado del script que hayamos introducido anteriormente.
  3. No te preocupes, estos pasos son más simples de lo que parecen!!!! Entonces… cada vez que dejemos un código de ejemplo como éste, puedes seguir estos pasos y ver los resultados por ti mismo. ¡Ojalá te animes!!!!

Link para descargar el editor de código Visual Studi Code!!

✅MÉTODO exec: regex.exec(string):

Ejecuta una búsqueda de coincidencia. Si encuentra una coincidencia, devuelve un array con información detallada sobre la coincidencia (la coincidencia completa, los grupos de captura, el índice donde encontró la coincidencia, la cadena original). Si no encuentra ninguna, devuelve null.

Particularidad: Con el flag g (global), exec() es muy útil para iterar sobre todas las coincidencias en una cadena, ya que actualiza la propiedad lastIndex de la RegEx para la siguiente búsqueda.

Cuándo usarlo: Cuando necesitás información detallada sobre la coincidencia (no solo true/false) o cuando querés recorrer todas las coincidencias una por una.

const regex = /a./;
console.log(regex.exec("banana")); // ["an"]Lenguaje del código: JavaScript (javascript)

Busca a seguido de cualquier carácter (.). Encuentra "an" como primera coincidencia.

B. Métodos del Objeto String:

✅MÉTODO match: string.match(regex):

Devuelve la primera coincidencia (sin /g) o todas (si usás /g).

Cuándo usarlo: Para obtener rápidamente todas las subcadenas que coinciden con un patrón global, o para obtener la primera coincidencia con detalles si no es global

const texto = "banana";
console.log(texto.match(/a./));    // ["an"]
console.log(texto.match(/a./g));   // ["an", "an"]Lenguaje del código: JavaScript (javascript)
  • Sin g: devuelve solo la primera coincidencia.
  • Con g: devuelve todas las coincidencias del patrón.
✅MÉTODO matchall: string.matchAll(regex) (requiere flag g):

Devuelve un iterador de todas las coincidencias. Cada elemento del iterador es un array similar al que devuelve exec(), con todas las propiedades (grupos de captura, índice, etc.). Es la forma moderna de obtener todas las coincidencias con sus detalles.

Cuándo usarlo: Cuando necesitás iterar sobre todas las coincidencias y obtener todos los detalles (incluyendo grupos de captura e índices) para cada una. Siempre se usa con el flag g.

const fraseContactos = "Email: [email protected], Tel: 123-456-7890. Correo: [email protected]";
const emailRegexGlobal = /(\w+)@([\w.]+)/g; // Captura usuario y dominio

for (const match of fraseContactos.matchAll(emailRegexGlobal)) {
    console.log(`Email encontrado: ${match[0]}`);
    console.log(`  Usuario: ${match[1]}`);
    console.log(`  Dominio: ${match[2]}`);
    console.log(`  En índice: ${match.index}`);
}
// Salida:
// Email encontrado: [email protected]
//   Usuario: info
//   Dominio: ejemplo.com
//   En índice: 7
// Email encontrado: [email protected]
//   Usuario: soporte
//   Dominio: sitio.net
//   En índice: 46
Lenguaje del código: JavaScript (javascript)
✅MÉTODO replace: string.replace(regex, reemplazo):

Busca coincidencias y las reemplaza por un nuevo texto.

reemplazo: Puede ser una cadena (ej. "***") o una función de JavaScript (para lógica de reemplazo más compleja).

Comportamiento:

  • Si la regex NO tiene el flag g, reemplaza solo la primera coincidencia.
  • Si la regex SÍ tiene el flag g, reemplaza todas las coincidencias.

Cuándo usarlo: Para limpiar datos, reformatear cadenas o censurar información.

const texto = "banana";
console.log(texto.replace(/a/, "x"));   // "bxnana"
console.log(texto.replace(/a/g, "x"));  // "bxnxnx"Lenguaje del código: JavaScript (javascript)
  • Sin g: solo reemplaza la primera a.
  • Con g: reemplaza todas las a.
✅MÉTODO replaceall: string.replaceAll(regex, reemplazo) (ES2021):

Similar a replace(), pero siempre reemplaza todas las ocurrencias sin necesidad del flag g en la RegEx. Puedes usarla con una RegEx sin flag g o con una string simple.

Cuándo usarlo: Cuando necesitás reemplazar todas las coincidencias de un patrón, de forma más explícita que replace con g.

const texto = "banana";
console.log(texto.replaceAll("a", "x")); // "bxnxnx"Lenguaje del código: JavaScript (javascript)

Reemplaza todas las letras a por x. Similar a replace(/a/g, "x").

✅MÉTODO search: string.search(regex):

Busca la primera coincidencia de la expresión regular y devuelve el índice (la posición) donde se encontró. Si no se encuentra ninguna coincidencia, devuelve -1.

Cuándo usarlo: Cuando solo necesitás saber si un patrón existe y dónde empieza la primera vez.

const miTexto = "Busca la palabra clave aquí.";
const regexClave = /clave/;

console.log(miTexto.search(regexClave)); // Salida: 18 (el índice donde empieza "clave")
console.log(miTexto.search(/inexistente/)); // Salida: -1
Lenguaje del código: JavaScript (javascript)
✅MÉTODO split: string.split(regex):

Divide una cadena en un array de subcadenas, utilizando la expresión regular como el delimitador (el separador).

Cuándo usarlo: Para descomponer una cadena compleja en partes más manejables basadas en patrones.

const texto = "uno,dos;tres cuatro";
console.log(texto.split(/[,; ]/)); // ["uno", "dos", "tres", "cuatro"]Lenguaje del código: JavaScript (javascript)

Separa el texto por comas, punto y coma o espacios usando una regex.

4. Banderas (Flags) en expresiones regulares

Las banderas son letras que se colocan después del patrón en una expresión regular para modificar su comportamiento de búsqueda.

/patrón/banderas //👈Lenguaje del código: JavaScript (javascript)

g (Global)

La bandera g le dice a tu expresión regular que busque todas las coincidencias en la cadena de texto, no solo la primera. Es fundamental cuando necesitas extraer o reemplazar múltiples ocurrencias de un patrón.

Ejemplo:

const texto = "El pato nada en el patio con otro pato.";
const regex = /pato/g; 
const coincidencias = texto.match(regex);
console.log(coincidencias); // Resultado: ["pato", "pato"]Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: Aquí, texto.match(regex) usa la bandera g con la expresión /pato/. Esto hace que el método match() devuelva un array que contiene todas las veces que la palabra «pato» aparece en el texto. Si no tuviéramos la g, solo se encontraría el primer «pato».

i (Case-insensitive)

La bandera i hace que tu búsqueda ignore las mayúsculas y minúsculas. Esto significa que, por ejemplo, «Hola», «hola» y «HOLA» serán tratados como la misma palabra por la expresión regular.

Ejemplo:

const frase = "JavaScript es genial. Me encanta javascript.";
const regex = /javascript/i; 
const encontrada = frase.match(regex);
console.log(encontrada); // Resultado: ["JavaScript", index: 0, input: "JavaScript es genial. Me encanta javascript.", groups: undefined]
Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: En este caso, /javascript/i con la bandera i hace que la expresión regular no distinga entre mayúsculas y minúsculas. Por lo tanto, aunque la frase contiene «JavaScript» (con ‘J’ mayúscula) y «javascript» (todo minúscula), la RegEx encuentra la primera ocurrencia («JavaScript») sin problema, ya que la ‘i’ le permite ignorar la diferencia de capitalización.

m (Multiline)

La bandera m es especial porque modifica el comportamiento de las anclas ^ (inicio de línea/cadena) y $ (fin de línea/cadena).

Sin la m, ^ y $ solo coinciden con el inicio y el final de toda la cadena de texto. Con la m, ^ también coincide con el inicio de cada nueva línea (después de un salto de línea \n), y $ coincide con el final de cada línea (antes de un \n).

Ejemplo:

const lista = "Item 1\nItem 2\nItem 3";
const regex = /^Item/gm; 
const todosLosItems = lista.match(regex);
console.log(todosLosItems);
Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: Aquí, ^Item busca «Item» al principio de una línea. Gracias a la bandera m, la expresión regular no solo busca «Item» al principio de la cadena ("Item 1"), sino que también lo busca al principio de cada nueva línea ("Item 2" y "Item 3"). La bandera g es usada en conjunto para que match() nos devuelva todas las coincidencias encontradas en esas múltiples líneas.

4.4. s (DotAll – «Single Line» en otras implementaciones)

Modifica el comportamiento del metacaracter . (punto). Normalmente, . coincide con cualquier carácter excepto los caracteres de nueva línea (\n, \r, etc.). Con la bandera s, . también coincide con los caracteres de nueva línea.

Cuándo usarla: Cuando necesitas que el patrón coincida con cualquier carácter, incluyendo los saltos de línea, lo cual es útil para procesar bloques de texto completos.

Ejemplo:

const textoConSaltos = "Primera línea\nSegunda línea";
const regexDotAll = /línea.Segunda/s;
const coincidenciaDotAll = textoConSaltos.match(regexDotAll);
console.log(coincidenciaDotAll); // Resultado: ["línea\nSegunda", index: 7, input: "Primera línea\nSegunda línea", groups: undefined]
Lenguaje del código: JavaScript (javascript)

Explicación: En este ejemplo, tenemos un texto que contiene un salto de línea (\n). Normalmente, el metacaracter . (punto) en una expresión regular coincide con cualquier carácter, excepto los saltos de línea. Sin embargo, al agregar la bandera s a /línea.Segunda/, estamos activando el modo «DotAll». Esto significa que el . ahora también puede coincidir con caracteres de nueva línea. Por lo tanto, la expresión regular línea.Segunda. Si la bandera s no estuviera presente, esta expresión regular no encontraría ninguna coincidencia, ya que el . normal se detendría ante el \n.

4.5. u (Unicode)

Habilita el soporte completo para caracteres Unicode. Esto es importante para trabajar correctamente con caracteres que están fuera del rango ASCII básico (por ejemplo, emojis, caracteres de otros idiomas como el chino, árabe, etc.) y para el correcto procesamiento de pares subrogados.

Cuándo usarla: Prácticamente siempre que tu aplicación maneje texto que pueda contener caracteres no ASCII. Es una buena práctica incluirla por defecto.

Ejemplo:

const textoUnicode = "😁 Mundo feliz";
const regexUnicode = /./u;
const coincidenciaUnicode = textoUnicode.match(regexUnicode);
console.log(coincidenciaUnicode); // Resultado: ["😁", index: 0, input: "😁 Mundo feliz", groups: undefined]
Lenguaje del código: JavaScript (javascript)

Explicación: Aquí, el texto contiene un emoji (😁). Los emojis y muchos otros caracteres de idiomas que no son el inglés se consideran parte del conjunto de caracteres Unicode, y a menudo se representan internamente como «pares subrogados» o puntos de código de mayor tamaño.

Normalmente, sin la bandera u, una expresión regular puede interpretar un solo carácter Unicode complejo como dos caracteres separados o simplemente no reconocerlo correctamente. Al incluir la bandera u en /./, le estamos indicando al motor de la expresión regular que opere en modo Unicode. Esto asegura que el . (punto), que normalmente coincide con un solo carácter básico, interprete correctamente el emoji 😁 como un único carácter Unicode completo, permitiendo que la coincidencia se realice como se espera y devolviendo el emoji como el primer carácter encontrado.

4.6. y (Sticky)

Asegura que la coincidencia solo pueda ocurrir exactamente en la posición especificada por la propiedad lastIndex de la expresión regular. Si la coincidencia no comienza en lastIndex, no se considera una coincidencia. A diferencia de g que busca en toda la cadena desde lastIndex, y es más estricta.

Cuándo usarla: Para un análisis muy preciso de la cadena, donde cada coincidencia debe estar inmediatamente adyacente a la anterior, o en una posición específica. Es menos común que las otras banderas para uso general.

Ejemplo:

const texto = "abc abc";
const regex = /abc/y; // Sticky: coincide solo desde lastIndex exacto

regex.lastIndex = 0;
console.log(regex.exec(texto)); // ["abc"] ✅ Encuentra "abc" en la posición 0

regex.lastIndex = 3;
console.log(regex.exec(texto)); // null ❌ En la posición 3 hay un espacio, no "abc"

regex.lastIndex = 4;
console.log(regex.exec(texto)); // ["abc"] ✅ Ahora sí encuentra "abc" en la posición 4Lenguaje del código: JavaScript (javascript)
  1. regex.lastIndex = 0: Intenta encontrar "abc" comenzando exactamente en el índice 0 → ✅ Éxito.
  2. regex.lastIndex = 3: En la posición 3 hay un espacio → ❌ Falla, no intenta buscar más adelante.
  3. regex.lastIndex = 4: Ahora en la posición 4 hay otro "abc" → ✅ Éxito.

Las banderas son herramientas poderosas para afinar el comportamiento de tus expresiones regulares, permitiéndote resolver una gama más amplia de problemas de procesamiento de texto con precisión.

5. Clases de caracteres (Character Classes)

Imagina que tenemos una caja con varios sellos de goma. Cuando usas una clase de caracteres en una expresión regular, es como si dijeras: «en este punto de la cadena, necesito que aparezca cualquiera de los sellos que están en esta caja». No importa cuál de ellos sea, siempre y cuando esté en la caja.

En expresiones regulares, un «conjunto de caracteres» te permite especificar un grupo de caracteres válidos para una posición específica en tu patrón. Esto es increíblemente útil cuando tenés varias opciones para un solo carácter.

Se escriben entre corchetes [ ]

NOTA! Todo lo que describimos sobre las clases de caracteres se utiliza directamente en la parte del patrón (ver sintaxis) de tu expresión regular.

5.1. [...]: Coincidir con cualquiera de los caracteres dentro de los corchetes

Esta es la forma más directa de crear un conjunto de caracteres. Todo lo que pones dentro de los corchetes [ y ] significa «coincide con cualquiera de estos caracteres que están aquí dentro, pero solo uno de ellos».

  • Sintaxis: [caracteres_posibles]
  • Significado: Si el carácter actual en la cadena de texto es uno de los que están listados dentro de los corchetes, hay una coincidencia.

Ejemplo:

const texto = "El día es gris.";
const regex = /[aeiou]/; // Coincide con cualquier vocal (una sola)
const coincidencia = texto.match(regex);
console.log(coincidencia); 
//0: "a"
  groups: undefined
  index: 5
  input: "El día es gris."
  length: 1[[Prototype]]: Array(0)Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo:

  1. const texto = "El día es gris.";: Esta es la cadena de texto donde vamos a buscar.
  2. const regex = /[aeiou]/;: Aquí definimos nuestra expresión regular.
    • Los corchetes [] indican una clase de caracteres.
    • Dentro de los corchetes, aeiou significa «cualquier vocal minúscula».
    • La expresión completa /aeiou/ significa: «busca la primera posición en el texto donde encuentres una ‘a’, una ‘e’, una ‘i’, una ‘o’ o una ‘u'».
  3. const coincidencia = texto.match(regex);: Usamos el método match() para aplicar la expresión regular al texto.

Cuando JavaScript ejecuta texto.match(/[aeiou]/), comienza a escanear «El día es gris.» desde el principio:

  • Encuentra ‘E’ (mayúscula) – no coincide con [aeiou].
  • Encuentra ‘l’ – no coincide.
  • Encuentra ‘ ‘ (espacio) – no coincide.
  • Encuentra ‘d’ – no coincide.
  • Encuentra ‘í’ – ¡Alto! Aunque ‘í’ es una vocal, nuestro patrón solo incluyó ‘a’, ‘e’, ‘i’, ‘o’, ‘u’ (sin tildes). Si quisieras que coincidiera, deberías incluirla en la clase, por ejemplo [aeiouáéíóú].
  • Encuentra ‘a’ – ¡Coincidencia! La ‘a’ es uno de los caracteres dentro de [aeiou].

Dado que match() sin la bandera g solo devuelve la primera coincidencia, el resultado será un array que contendrá ["a"], junto con metadatos como el index (la posición donde se encontró, en este caso, 5).

IMPORTANT!! Dentro de los corchetes, la mayoría de los metacaracteres (como ., *, +, ?, |, (, )) pierden su significado especial y se tratan como caracteres literales. Sin embargo, ^ (al principio), - (en medio), y \ (escape) mantienen un significado especial dentro de [].

5.2. [^...]: Negación, coincidir con cualquier carácter excepto los dentro de los corchetes

Cuando pones un ^ inmediatamente después del corchete de apertura [, la clase de caracteres se convierte en una negación. Significa «coincide con cualquier carácter que NO esté en la lista dentro de los corchetes».

  • Sintaxis: [^caracteres_a_excluir]
  • Significado: Si el carácter actual en la cadena de texto no es uno de los que están listados dentro de los corchetes, hay una coincidencia.

Ejemplos:

const frase = "Hoy es 07 de Julio.";
const regexNoDigito = /[^0-9]/; // Coincide con cualquier carácter que NO sea un dígito
const coincidencia = frase.match(regexNoDigito);
console.log(coincidencia); // Resultado: ["H", index: 0, input: "Hoy es 07 de Julio.", groups: undefined]
Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo:

  1. const frase = "Hoy es 07 de Julio.";: Esta es la cadena de texto en la que vamos a buscar.
  2. const regexNoDigito = /[^0-9]/;: Aquí definimos la expresión regular.
    • Los corchetes [] indican una clase de caracteres.
    • El ^ inmediatamente después del corchete de apertura [ convierte la clase en una negación.
    • 0-9 dentro de los corchetes define un rango que incluye todos los dígitos del 0 al 9.
    • Entonces, /[^0-9]/ significa: «busca la primera posición en el texto donde encuentres cualquier carácter que no sea un dígito«.
  3. const coincidencia = frase.match(regexNoDigito);: Aplicamos la expresión regular a la frase.

Cuando JavaScript ejecuta frase.match(/[^0-9]/), comienza a escanear «Hoy es 07 de Julio.» desde el principio:

  • En el índice 0, encuentra ‘H’.
  • Pregunta: «¿’H’ es un dígito?» No.
  • Conclusión: Como ‘H’ no es un dígito, ¡hay una coincidencia! La búsqueda se detiene (ya que no se usa la bandera g).

El resultado en la consola es un array que contiene ["H"], ya que ‘H’ es el primer carácter que no es un dígito en la cadena, junto con metadatos como su index (0).

5.3. Rangos: [a-z], [0-9], [A-Za-z0-9]

Escribir todos los caracteres individualmente en una clase de caracteres puede ser tedioso ([abcde...]). Para eso existen los rangos, que usan el guion -. Un rango especifica un conjunto de caracteres consecutivos en la tabla ASCII (o Unicode).

  • [a-z]: Coincide con cualquier letra minúscula desde ‘a’ hasta ‘z’.
  • [A-Z]: Coincide con cualquier letra mayúscula desde ‘A’ hasta ‘Z’.
  • [0-9]: Coincide con cualquier dígito desde ‘0’ hasta ‘9’ (esto es equivalente al atajo \d).
  • [a-zA-Z]: Coincide con cualquier letra (minúscula o mayúscula).
  • [A-Za-z0-9]: Coincide con cualquier letra o dígito (equivalente al atajo \w si no incluye el guion bajo _).
  • [0-5]: Coincide con cualquier dígito del 0 al 5.

Ejemplos:

const codigoProducto = "ABC-12345-X";
const regexRango = /[0-9]{5}/; // Coincide con exactamente 5 dígitos
const coincidencia = codigoProducto.match(regexRango);
console.log(coincidencia); // Resultado: ["12345", index: 4, input: "ABC-12345-X", groups: undefined]
Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo:

  1. const codigoProducto = "ABC-12345-X";: Esta es la cadena de texto donde vamos a buscar.
  2. const regexRango = /[0-9]{5}/;: Aquí definimos nuestra expresión regular.
    • Los corchetes [] indican una clase de caracteres.
    • 0-9 dentro de los corchetes define un rango que incluye todos los dígitos del 0 al 9. Esto es una forma más corta de escribir [0123456789].
    • {5} es un cuantificador que le dice a la expresión regular que el elemento anterior (en este caso, cualquier dígito del 0 al 9) debe aparecer exactamente 5 veces.
    • Así, /[0-9]{5}/ significa: «busca la primera secuencia de exactamente cinco dígitos consecutivos».
  3. const coincidencia = codigoProducto.match(regexRango);: Aplicamos la expresión regular a la cadena.

Cuando JavaScript ejecuta codigoProducto.match(/[0-9]{5}/), escanea la cadena:

  • Ignora «ABC-«.
  • Llega a «12345». Pregunta: «¿Estos son 5 dígitos consecutivos?» Sí.
  • ¡Coincidencia! La búsqueda se detiene (ya que no se usa la bandera g).

El resultado en la consola es un array que contiene ["12345"], ya que es la primera secuencia de cinco dígitos encontrados, junto con metadatos como su index (4).

Consejo: La posición del guion - dentro de [] es importante. Si es el primer o último carácter, se trata como un guion literal. Si está entre dos caracteres, define un rango ([a-z]).

6. Caracteres de escape (Escaping Special Characters)

En el mundo de las expresiones regulares, hay ciertos caracteres que no se representan a sí mismos de forma literal. En cambio, tienen un significado especial que les permite actuar como «comandos» o «operadores» dentro de tu patrón.

6.1. Los caracteres especiales o metacaracteres son:

Estos son los «metacaracteres» que debes tener en cuenta. Si los pones en tu patrón sin escaparlos, la expresión regular no los interpretará como el carácter literal, sino como su función especial:

MetacarácterSignificado / FunciónEjemploCoincide con…
.Cualquier carácter excepto salto de línea (\n)/a.c/"abc", "a7c", etc.
*Cero o más repeticiones del carácter o grupo anterior/a*/"", "a", "aaa", etc.
+Una o más repeticiones del carácter o grupo anterior/a+/"a", "aaa" pero no ""
?Cero o una vez del carácter anterior o vuelve cuantificador «perezoso» si se usa después de * o +/colou?r/"color", "colour"
^Coincide con el inicio de cadena (o de línea con flag m)/^Hola/"Hola mundo" si empieza con "Hola"
$Coincide con el final de cadena (o de línea con flag m)/mundo$/"Hola mundo" si termina en "mundo"
( )Agrupan patrones y crean grupos de captura/(abc)+/"abcabc"
[ ]Define una clase de caracteres (un conjunto a permitir)/[aeiou]/cualquier vocal
{ }Cuantificadores de rango (repeticiones)/a{2,4}/"aa", "aaa", "aaaa"
``Alternancia (OR lógico)`/rojo
\Escapa un metacarácter o representa un carácter especial (como \d, \s, etc.)/\./ o /\d/un "." literal o cualquier dígito (0-9)

6.2. Cómo escapar un carácter especial con \

Cuando queremos buscar uno de estos metacaracteres literalmente en tu texto (es decir, querés encontrar el símbolo . y no «cualquier carácter»), tenemos que escaparlo. Esto se hace colocando una barra invertida (\) justo antes del carácter especial.

La barra invertida le dice al motor de la expresión regular: «Ojo, el siguiente carácter no es un comando especial, trátalo como un carácter normal que quiero buscar».

Ejemplos de escape:

Si quieres buscar…Sintaxis RegEx (Literal)Explicación
Un punto literal ./\./. sin escape es «cualquier carácter». \. busca el símbolo de punto.
Un asterisco literal */\*/* sin escape es «cero o más». \* busca el símbolo de asterisco.
Un signo de más literal +/\+/+ sin escape es «uno o más». \+ busca el símbolo de más.
Un signo de interrogación ?/\?/? sin escape es «cero o uno». \? busca el símbolo de interrogación.
Un paréntesis de apertura (/\(/( sin escape abre un grupo. \( busca el símbolo de paréntesis.
Una barra invertida literal \/\\/\ es el carácter de escape. Para buscarlo a él mismo, hay que escaparlo.

6.3. Ejemplos prácticos:

1️⃣ Buscar una URL con puntos: Si tienes www.ejemplo.com y quieres buscar el dominio completo

const url = "Visita www.mi-sitio.com para más info.";
const regexDominio = /www\.mi-sitio\.com/; // Escapamos los puntos
console.log(url.match(regexDominio)); // Salida: ["www.mi-sitio.com", ...]Lenguaje del código: JavaScript (javascript)

Si no escaparas los puntos (/www.mi-sitio.com/), la RegEx buscaría «www» seguido de cualquier carácter, seguido de «mi-sitio», seguido de cualquier carácter, y luego «com». Podría coincidir con «wwwXmi-sitioYcom».

2️⃣ Buscar un precio con símbolo de dólar: Si tienes $10.50 y quieres buscarlo específicamente:

const precio = "El costo es $10.50.";
const regexPrecio = /\$\d+\.\d{2}/; // Escapamos $ y .
console.log(precio.match(regexPrecio)); // Salida: ["$10.50", ...Lenguaje del código: JavaScript (javascript)

RESUMEN:

  • REGLA GENERAL: Si un carácter tiene un significado especial en expresiones regulares y quieres buscarlo literalmente, ponle una barra invertida (\) delante.
  • IMPORTANTE CON new RegExp(): Recuerda que si construyes tu patrón como una cadena de texto para new RegExp(), necesitarás doble barra invertida (\\) para escapar un metacaracter. Esto es porque la primera \ escapa la segunda para la cadena de JavaScript.
    • Ejemplo: new RegExp("\\.") para buscar un punto literal.

Dominar el escape de caracteres es esencial para escribir expresiones regulares precisas y evitar comportamientos inesperados en tus búsquedas y validaciones.

7. Cuantificadores (Quantifiers)

El concepto central de un cuantificador es simple: indican la cantidad de veces que un elemento (el carácter o grupo justo antes del cuantificador) debe repetirse para que el patrón sea considerado una coincidencia.

7.1. * (Cero o más veces)

Este cuantificador significa que el elemento que lo precede puede aparecer cero o más veces. Es muy flexible y se usa cuando la presencia del elemento es opcional y su repetición es ilimitada.

Ejemplo:

const texto = "color, coloor, coor, cooor";
const regex = /colo*r/g; // La 'o' puede aparecer cero o más veces
const coincidencias = texto.match(regex);
console.log(coincidencias); // Resultado: ["color", "coloor"]Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: La expresión regular /colo*r/g busca la secuencia «col», seguida de cero o más ‘o’s, y finalmente una ‘r’.

  • "color" ✅ → tiene una "o" después de "l" → coincide
  • "coloor" ✅ → tiene dos "o" → también vale
  • "coor" ❌ → le falta la letra l, no coincide
  • "cooor" ❌ → también le falta la l, no coincide

La bandera g (global) se usa para encontrar todas las ocurrencias en la cadena.

7.2. + (Una o más veces)

Este cuantificador indica que el elemento que lo precede debe aparecer una o más veces. A diferencia de *, el + exige que el elemento esté presente al menos una vez para que haya una coincidencia.

Ejemplo:

const numeros = "ID: 12345, Codigo: 67, PIN: 8";
const regex = /\d+/g; // Uno o más dígitos
const coincidencias = numeros.match(regex);
console.log(coincidencias); // Resultado: ["12345", "67", "8"]
Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: La expresión regular /\d+/g busca uno o más dígitos (\d significa cualquier dígito).

  • En «12345», encuentra una secuencia de cinco dígitos.
  • En «67», encuentra dos dígitos.
  • En «8», encuentra un dígito. La bandera g asegura que se encuentren todas estas secuencias de dígitos. Si alguna parte de la cadena no tuviera al menos un dígito, no habría coincidencia en esa parte.

7.3. ? (Cero o una vez – opcional)

El cuantificador ? hace que el elemento que lo precede sea opcional: puede aparecer una vez o no aparecer ninguna.

Ejemplo:

const palabras = "color, colour, reencuentro";
const regex = /colou?r/g; // La 'u' es opcional
const coincidencias = palabras.match(regex);
console.log(coincidencias); // Resultado: ["color", "colour"]
Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: La expresión regular /colou?r/g busca la secuencia «colo», seguida opcionalmente de una ‘u’, y luego una ‘r’.

  • En «color», coincide porque la ‘u’ es opcional (no está presente).
  • En «colour», coincide porque la ‘u’ está presente una vez.
  • En «reencuentro», no hay coincidencia completa con el patrón.

7.4. {n} (Exactamente n veces)

Cuando necesitas que un elemento se repita un número exacto de veces, usas las llaves con un número dentro.

Ejemplo:

const codigos = "ABCD-1234, EFGH-56789, IJKL-0000";
const regex = /\b[A-Z]{4}\b/g; // Exactamente 4 letras mayúsculas, como palabra completa
const coincidencias = codigos.match(regex);
console.log(coincidencias); // Resultado: ["ABCD", "IJKL"]
Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: La expresión regular /\b[A-Z]{4}\b/g busca una secuencia de exactamente 4 letras mayúsculas ([A-Z]) que formen una palabra completa (\b son límites de palabra).

  • «ABCD» cumple con ser 4 letras mayúsculas como palabra.
  • «EFGH-56789» no se cuenta como una palabra de 4 letras solas.
  • «IJKL» también cumple con la condición.

7.5. {n,} (n o más veces)

Este cuantificador indica que el elemento debe repetirse al menos n veces, pero puede ser cualquier número mayor. No hay un límite superior.

Ejemplo:

const contraseñas = "pass123, short, v3ryL0ngP4ssword";
const regex = /\w{8,}/g; // 8 o más caracteres de palabra
const coincidencias = contraseñas.match(regex);
console.log(coincidencias); // Resultado: ["v3ryL0ngP4ssword"]
Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: La expresión regular /\w{8,}/g busca secuencias de 8 o más caracteres de palabra (\w incluye letras, números y guion bajo).

  • «pass123» tiene 7 caracteres, por lo tanto no coincide.
  • «short» tiene 5 caracteres, tampoco coincide.
  • «v3ryL0ngP4ssword» tiene más de 8 caracteres, por lo que coincide.

7.6. {n,m} (Entre n y m veces)

Este cuantificador te permite especificar un rango de repeticiones: el elemento debe aparecer al menos n veces, pero no más de m veces.

Ejemplo:

const temperaturas = "Temp: 5C, Max: 25C, Min: -10C, Actual: 150C";
const regex = /\b\d{1,2}C\b/g; // 1 o 2 dígitos seguidos de 'C', como palabra
const coincidencias = temperaturas.match(regex);
console.log(coincidencias); // Resultado: ["5C", "25C", "10C"]Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: La expresión regular /\b\d{1,2}C\b/g busca una palabra que consista en 1 o 2 dígitos (\d{1,2}) seguidos de la letra ‘C’.

  • «5C» tiene 1 dígito seguido de ‘C’, coincide.
  • «25C» tiene 2 dígitos seguidos de ‘C’, coincide.
  • «-10C» no coincide directamente porque el guion es parte de la «palabra». Si solo buscamos el «10C», el patrón podría ser diferente o el contexto más específico. Sin embargo, para «10C» como subcadena dentro de «-10C», solo \d{1,2} coincidiría con «10» y luego «C».
  • «150C» no coincide porque tiene 3 dígitos, y el rango especifica un máximo de 2.

7.8. Cuantificadores avidos (Greedy) vs. Perezosos (Lazy)

Por defecto, todos los cuantificadores (*, +, ?, {n}, {n,}, {n,m}) son ávidos (greedy). Esto significa que intentarán coincidir con la mayor cantidad de texto posible mientras el patrón general siga siendo válido.

Si querés que sean perezosos (lazy), es decir, que coincidan con la menor cantidad de texto posible, le agregás un ? después del cuantificador: *?, +?, ??, {n,}?, {n,m}?.

Ejemplo de Greedy vs. Lazy:

const htmlString = "Este es un <b>texto en negrita</b> y este otro es <b>más negrita</b>.";

// Cuantificador Ávido (Greedy)
// Busca '<b>', luego CUALQUIER COSA (.*) de forma ávida, hasta el ÚLTIMO '</b>'
const greedyRegex = /<b>.*<\/b>/; 
const greedyMatch = htmlString.match(greedyRegex);
console.log("Ávido (Greedy):", greedyMatch[0]); 
// Resultado: Ávido (Greedy): <b>texto en negrita</b> y este otro es <b>más negrita</b>.

// Cuantificador Perezoso (Lazy)
// Busca '<b>', luego CUALQUIER COSA (.*?) de forma perezosa, hasta el PRIMER '</b>'
const lazyRegex = /<b>.*?<\/b>/;
const lazyMatch = htmlString.match(lazyRegex);
console.log("Perezoso (Lazy):", lazyMatch[0]);
// Resultado: Perezoso (Lazy): <b>texto en negrita</b>Lenguaje del código: HTML, XML (xml)

Explicación:

htmlString: Es la cadena de texto de entrada que contiene dos pares de etiquetas <b>.

CUANTIFICADOR Ávido (greedyRegex = /<b>.*<\/b>/;):**

  • <b>: Coincide con la etiqueta de apertura literal <b>..*: Este es el punto clave. . coincide con cualquier carácter (excepto nueva línea), y * significa «cero o más veces». Como * es ávido por defecto, intentará coincidir con la mayor cantidad de caracteres posible.<\/b>: Coincide con la etiqueta de cierre literal </b>. El / está escapado (\/) porque es un carácter especial en la sintaxis de la expresión regular literal.

Cuando greedyRegex se ejecuta, encuentra el primer <b>. Luego, el .* empieza a coincidir con «texto en negrita</b> y este otro es «. El .* sigue «comiendo» caracteres hasta que no puede más, es decir, hasta que encuentra el último</b> en la cadena. Por eso, la coincidencia abarca desde el primer <b> hasta el último </b>.

La elección entre un cuantificador ávido o perezoso es crucial para asegurarte de que tu expresión regular capture exactamente la porción de texto que deseas, especialmente cuando trabajas con estructuras repetitivas como HTML o XML.

CUANTIFICADOR Perezoso (lazyRegex = /<b>.*?<\/b>/;):**

  • <b>: Coincide con la etiqueta de apertura literal <b>..*?: Aquí está la diferencia. El . coincide con cualquier carácter, pero el *? es el cuantificador perezoso. Esto significa que coincidirá con la menor cantidad de caracteres posible.<\/b>: Coincide con la etiqueta de cierre literal </b>.

Cuando lazyRegex se ejecuta, encuentra el primer <b>. Luego, el .*? empieza a coincidir. Pero como es perezoso, en cuanto encuentra la primera ocurrencia de </b> que completa el patrón, se detiene. No sigue «comiendo» texto, por eso solo coincide con "<b>texto en negrita</b>".

8. Anclas más usadas

8.1. ^ (Inicio de la Cadena/Línea)

El ancla ^ coincide con el inicio de la cadena de texto. Si se usa junto con la bandera m (multiline), también coincide con el inicio de cada nueva línea dentro de la cadena.

Ejemplo:

const texto = "Hola mundo\nHola de nuevo";
const regexInicio = /^Hola/; // Coincide con "Hola" solo al inicio de la cadena
const regexInicioMulti = /^Hola/m; // Coincide con "Hola" al inicio de cada línea

console.log(texto.match(regexInicio));     // Resultado: ["Hola", index: 0, input: "Hola mundo\nHola de nuevo", groups: undefined]
console.log(texto.match(regexInicioMulti)); // Resultado: ["Hola", "Hola"] (con la bandera 'g' también para ver ambas)
Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: En el primer caso, /^Hola/ busca «Hola» solo si está al principio de toda la cadena "Hola mundo\nHola de nuevo". Como «Hola» está al principio, lo encuentra. En el segundo caso, al añadir la bandera m a /^Hola/m, el ^ ahora también considera los inicios de cada línea. Por eso, si usaras texto.match(/^Hola/gm) (con g para obtener todas las coincidencias), obtendrías ambas «Hola» porque están al inicio de sus respectivas líneas. El ejemplo dado con solo m por defecto encuentra la primera «Hola» al inicio de la primera línea.

8.2. $ (Fin de la Cadena/Línea)

El ancla $ coincide con el fin de la cadena de texto. Al igual que ^, si se usa con la bandera m (multiline), también coincide con el fin de cada nueva línea.

Ejemplo:

const frase = "Fin de la frase.\nOtra frase que termina.";
const regexFin = /frase.$/; // Coincide con "frase." solo al final de la cadena
const regexFinMulti = /termina.$/m; // Coincide con "termina." al final de cada línea

console.log(frase.match(regexFin));     // Resultado: ["frase.", index: 12, input: "Fin de la frase.\nOtra frase que termina.", groups: undefined]
console.log(frase.match(regexFinMulti)); // Resultado: ["termina.", index: 32, input: "Fin de la frase.\nOtra frase que termina.", groups: undefined]
Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: Para /frase.$/, el $ asegura que «frase.» solo coincida si está justo antes del final de toda la cadena. Lo encuentra en «Fin de la frase.». Para /termina.$/m, la bandera m hace que $ busque el final de cada línea. Por eso, el patrón «termina.» coincide al final de la segunda línea. (Nota: el . antes del $ coincide con el punto literal gracias a que no es un metacaracter con . ni nada parecido, no es por la bandera s)

8.3. \b (Límite de Palabra)

El ancla \b es un límite de palabra. Coincide con la posición donde un carácter de «palabra» (\w, es decir, letras, números o guion bajo) no está precedido ni seguido por otro carácter de «palabra». Esto incluye el inicio o fin de la cadena, espacios, signos de puntuación, etc. Es excelente para encontrar palabras completas y evitar coincidencias parciales.

Ejemplo:

const texto = "Mi casa es blanca. La casita está cerca.";
const regexPalabra = /\bcas\b/g; // Coincide con la palabra "cas" sola
const regexPalabraCompleta = /\bcasa\b/g; // Coincide con la palabra "casa" sola

console.log(texto.match(regexPalabra));       // Resultado: null
console.log(texto.match(regexPalabraCompleta)); // Resultado: ["casa"]Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: En el primer caso, /\bcas\b/g busca la palabra «cas» rodeada de límites de palabra. Como en «casa» o «casita», «cas» está pegada a otras letras, no se considera una palabra completa por sí misma, y por eso devuelve null. En el segundo caso, /\bcasa\b/g busca la palabra «casa» completa. La encuentra en «Mi casa es blanca.» porque está rodeada de espacios y puntuación, lo que marca sus límites de palabra. La \b impide que coincida con «casita».

8.4. \B (No es un Límite de Palabra)

El ancla \B es lo opuesto a \b. Coincide con una posición que NO es un límite de palabra. Es decir, la posición debe estar dentro de una secuencia de caracteres de palabra.

Ejemplo:

const texto = "reemplazar palabras clave";
const regexNoLimite = /\Bra/g; // Coincide con "ra" que NO está al inicio/fin de palabra
const regexNoLimiteCompleto = /re\B/g; // Coincide con "re" no al final de una palabra

console.log(texto.match(regexNoLimite));       // Resultado: ["ra"] (de "palabras")
console.log(texto.match(regexNoLimiteCompleto)); // Resultado: ["re"] (de "reemplazar")Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: Para /\Bra/g, la RegEx busca «ra» solo si no está al inicio o fin de una palabra. En «palabras», la «ra» está en el medio de una palabra, por lo que coincide. No coincidiría si buscara «ra» al inicio de una palabra. Para /re\B/g, busca «re» solo si no está al final de una palabra. En «reemplazar», «re» no está al final de la palabra, por lo que coincide. Si la palabra fuera solo «re», no coincidiría.

9. Atajos de clases de caracteres

9.1. \d (Dígito)

El atajo \d coincide con cualquier dígito numérico del 0 al 9. Es exactamente lo mismo que usar [0-9].

Ejemplo:

const texto = "Mi edad es 30 años y mi PIN es 1234.";
const regex = /\d+/g; // Coincide con una o más dígitos
const coincidencias = texto.match(regex);
console.log(coincidencias); // Resultado: ["30", "1234"]
Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: La expresión regular /\d+/g busca una o más (+) ocurrencias de cualquier dígito (\d). En el texto, primero encuentra «30» y luego «1234». La bandera g asegura que ambas secuencias de dígitos sean encontradas y devueltas en un array.

9.2. \D (No es un Dígito)

El atajo \D coincide con cualquier carácter que NO sea un dígito numérico. Es lo opuesto a \d, equivalente a [^0-9].

Ejemplo:

const identificador = "ID-ABC-123";
const regex = /\D+/g; // Coincide con uno o más caracteres que no sean dígitos
const coincidencias = identificador.match(regex);
console.log(coincidencias); // Resultado: ["ID-ABC-"]
Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: La expresión regular /\D+/g busca una o más (+) ocurrencias de cualquier carácter que no sea un dígito (\D). En el identificador, el motor encuentra «ID-ABC-«. Después de eso, encuentra «123», que son dígitos, por lo que esa parte no coincide con \D+. La bandera g se usa para buscar todas las ocurrencias, pero en este caso solo hay una secuencia de no-dígitos.

9.3. \w (Carácter de Palabra)

El atajo \w coincide con cualquier carácter que se considera parte de una «palabra». Esto incluye letras (mayúsculas y minúsculas), dígitos y el guion bajo (_). Es equivalente a [A-Za-z0-9_].

Ejemplo:

const cadena = "Usuario_123, [email protected]";
const regex = /\w+/g; // Coincide con una o más caracteres de palabra
const coincidencias = cadena.match(regex);
console.log(coincidencias); // Resultado: ["Usuario_123", "Correo", "dominio", "com"]
Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: La expresión regular /\w+/g busca una o más (+) ocurrencias de caracteres de palabra (\w). En la cadena, encuentra «Usuario_123» (incluyendo el guion bajo y los números), luego «Correo», y después «dominio» y «com». Los caracteres como @ y . no son caracteres de palabra, por lo que actúan como separadores.

9.4. \W (No es un Carácter de Palabra)

El atajo \W coincide con cualquier carácter que NO sea un carácter de palabra. Es decir, coincide con cualquier cosa que no sea una letra, un dígito o un guion bajo. Es lo opuesto a \w, equivalente a [^A-Za-z0-9_].

Ejemplo:

const texto = "Hola-Mundo! Esto es una prueba.";
const regex = /\W+/g; // Coincide con uno o más caracteres que no son de palabra
const coincidencias = texto.match(regex);
console.log(coincidencias); // Resultado: ["-", "! ", " "]
Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: La expresión regular /\W+/g busca una o más (+) ocurrencias de caracteres que no son de palabra (\W). En el texto, encuentra el guion -, luego la exclamación ! seguida de un espacio, y finalmente el espacio entre «es» y «una» y entre «una» y «prueba».

9.5. \s (Espacio en Blanco)

El atajo \s coincide con cualquier carácter de espacio en blanco. Esto incluye el espacio (), tabulaciones (\t), saltos de línea (\n), retornos de carro (\r), avances de página (\f), y tabulaciones verticales (\v).

Ejemplo:

const direccion = "Calle Falsa 123\nCiudad, País";
const regex = /\s+/g; // Coincide con uno o más espacios en blanco
const coincidencias = direccion.match(regex);
console.log(coincidencias); // Resultado: [" ", "\n"]
Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: La expresión regular /\s+/g busca una o más (+) ocurrencias de cualquier carácter de espacio en blanco (\s). En la direccion, encuentra el espacio entre «Calle» y «Falsa», luego el espacio entre «Falsa» y «123», y finalmente el salto de línea (\n) entre «123» y «Ciudad».

9.6. \S (No es un Espacio en Blanco)

El atajo \S coincide con cualquier carácter que NO sea un espacio en blanco. Es lo opuesto a \s.

Ejemplo:

const frase = "  Muchos   espacios  ";
const regex = /\S+/g; // Coincide con uno o más caracteres que no son espacios en blanco
const coincidencias = frase.match(regex);
console.log(coincidencias); // Resultado: ["Muchos", "espacios"]
Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: La expresión regular /\S+/g busca una o más (+) ocurrencias de cualquier carácter que no sea un espacio en blanco (\S). En la frase, encuentra la palabra «Muchos» y luego la palabra «espacios». Los múltiples espacios entre ellas son ignorados por el patrón \S+.

10. Agrupaciones y alternativas

Son partes de una expresión regular que se encierran entre paréntesis ( ).
Sirven para:

  • Tratar varias partes del patrón como una sola unidad.
  • Aplicar cuantificadores o modificadores a todo el grupo.
  • Capturar el texto que coincide con esa parte para poder usarlo después.

10.1. Grupos de captura:

Los grupos de captura son partes de una expresión regular que se agrupan usando paréntesis ( ).
Cuando una parte del patrón está entre paréntesis:

  • La expresión regular puede tratarla como una sola unidad (por ejemplo, repetirla o aplicarle cuantificadores).
  • El texto que coincida con lo que está dentro del grupo se «captura», es decir, queda guardado y podés recuperarlo después.

¿Para qué sirven?

  • Capturar partes específicas del texto que querés extraer.
  • Aplicar cuantificadores (+, *, {n}) a varias partes del patrón juntas.
  • Reutilizar partes del patrón usando referencias posteriores (\1, $1, etc.).
  • Facilitar la lectura y organización de patrones complejos.

¿Cómo se usan?

La sintaxis es muy simple:

(patrón) //Envolvemos el patrón entre paréntesisLenguaje del código: JavaScript (javascript)

✔ Ejemplo básico: /(\d+)/
Este patrón busca uno o más dígitos juntos y los captura como un grupo.

Ejemplo práctico y sencillo

let texto = "Mi teléfono es 12345.";
let regex = /(\d+)/;
let resultado = regex.exec(texto);

console.log(resultado);
/*
[
  "12345",   // resultado[0]: el texto completo que hizo match
  "12345",   // resultado[1]: lo que capturó el primer grupo ()
  index: 16, // dónde empezó el match dentro del texto original
  input: "Mi teléfono es 12345.",  // el texto completo
  groups: undefined
]
*/Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo:

Primero definimos un texto que dice "Mi teléfono es 12345.".
La expresión regular /(\d+)/ busca uno o más dígitos (\d+) y esos dígitos están dentro de paréntesis, lo que significa que serán capturados como un grupo.

Después usamos exec(), que devuelve un array con el resultado completo:

  • En la posición [0], siempre devuelve todo el texto que coincide con el patrón completo. En este caso, "12345".
  • En la posición [1], devuelve lo que capturó el primer grupo de paréntesis, que en este caso es también "12345", porque el patrón completo es el grupo.
  • También nos muestra en qué posición del texto original comenzó la coincidencia (índice 16) y cuál era el texto completo donde buscó.

10.2. la Alternancia.

La alternancia en expresiones regulares es una forma de decir «o».
Se escribe usando el símbolo | (barra vertical) dentro o fuera de un grupo de captura.

✅ ¿Para qué sirve?

Sirve para indicar que cualquiera de varias opciones es válida.
Por ejemplo, si querés buscar «gato» o «perro», usás:

(gato|perro)

Esto encuentra cualquiera de esas dos palabras.

✅ ¿Cómo se usa?

Si querés que la alternancia sea entre caracteres individuales, podés usar corchetes [abc].
Pero si querés alternar palabras, frases o patrones más grandes, usás paréntesis con | así: (opción1|opción2|opción3).

10.3. Los grupos no capturantes.

Un grupo no capturante es como un grupo normal, pero no guarda el contenido que coincide.
Se escribe así:

(?:patrón)Lenguaje del código: CSS (css)

Sirve para agrupar partes de una expresión regular, pero sin que esas partes se guarden como un grupo de captura.

✅ ¿Para qué sirven?

  • Aplicar cuantificadores o alternancia a varias partes del patrón.
  • Organizar el patrón, pero sin capturar el contenido intermedio.
  • Evitar que el resultado de match(), exec() o matchAll() tenga demasiados grupos que no necesitás guardar.

✅ ¿Cómo se usan?

Simplemente ponés ?: después del primer paréntesis.
Así le indicás a JavaScript que no capture ese grupo, pero que igual lo tenga en cuenta en la búsqueda.

11. Lookahead y Lookbehind.

Los Lookahead ((?=...) y (?!...)) y Lookbehind ((?<=...) y (?<!...)) son construcciones que te permiten definir condiciones sobre los caracteres que preceden o siguen a tu patrón principal, sin que esos caracteres de condición formen parte de la coincidencia que obtienes.

  • NO consumen caracteres, es decir, no forman parte del resultado de la búsqueda.
  • Solo verifican si hay o no hay un patrón antes o después de la posición actual.

Lookahead ➔ mira hacia adelante (después del patrón actual).

Lookbehind ➔ mira hacia atrás (antes del patrón actual).

✅ ¿Para qué sirven?

  • Para buscar algo solo si está seguido o precedido por otro patrón.
  • Para excluir o incluir condiciones, sin que el texto usado en la condición sea parte del resultado.

11.1. Lookahead Positivo: (?=...) (Positivo de Anticipación)

Este lookahead asegura que lo que está dentro de los paréntesis (?=...) siga a tu patrón principal, pero sin incluirlo en la coincidencia. Es decir, el patrón solo coincide si es seguido por el contenido del lookahead.

Ejemplo: Queremos encontrar nombres de frutas, pero solo si están seguidas por la palabra «madura».

const textoFrutas = "La manzana madura, la pera verde y la uva madura.";
// Patrón: Una palabra (\w+) seguida por (pero no capturando) un espacio y "madura".
const regexFrutaMadura = /\b(\w+)\b(?=\s+madura)/g; 
const coincidencias = textoFrutas.match(regexFrutaMadura);
console.log(coincidencias); // Resultado: ["manzana", "uva"]
Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: La expresión regular /\b(\w+)\b(?=\s+madura)/g busca palabras completas que estén seguidas por » madura».

  • \b(\w+)\b: Este es nuestro patrón principal. Busca una palabra completa (\b marca límites de palabra) y la captura en el grupo 1 ((\w+)).
  • (?=\s+madura): Este es el Lookahead Positivo. No consume caracteres. Simplemente verifica que, después de la palabra capturada, haya uno o más espacios (\s+) seguidos de la palabra «madura». Si esta condición se cumple, entonces \b(\w+)\b puede coincidir en esa posición.
  • g: La bandera global para encontrar todas las ocurrencias.

Así, la RegEx encuentra «manzana» (porque está seguida de » madura») y «uva» (también seguida de » madura»), pero no incluye » madura» en el resultado de la coincidencia porque está dentro del lookahead.

11.2. Lookahead Negativo: (?!...) (Negativo de Anticipación)

Este lookahead asegura que lo que está dentro de los paréntesis (?!...) NO siga a tu patrón principal. Es decir, el patrón solo coincide si NO es seguido por el contenido del lookahead.

Ejemplo: Queremos encontrar palabras que terminan en «ing», pero solo si NO son «going».

const textoVerbos = "going, running, playing, doing.";
// Patrón: Cualquier palabra que NO sea "go" seguida de "ing".
const regexNoGoing = /\b(?!go)\w+ing\b/g; 
const coincidencias = textoVerbos.match(regexNoGoing);
console.log(coincidencias); // Resultado: ["running", "playing", "doing"]
Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: La expresión regular /\b(?!go)\w+ing\b/g busca palabras que terminan en «ing» pero no son «going».

  • \b: Límite de palabra.
  • (?!go): Este es el Lookahead Negativo. No consume caracteres. Asegura que la posición actual no sea seguida inmediatamente por la secuencia «go». Si la posición es seguida por «go», entonces todo el patrón falla en ese punto.
  • \w+ing\b: Este es el patrón principal. Coincide con uno o más caracteres de palabra seguidos de «ing», terminando en un límite de palabra.

Por lo tanto, la RegEx encuentra «running», «playing» y «doing» porque no están precedidas por «go», pero omite «going» debido a la condición negativa del lookahead.

11.3. Lookbehind Positivo: (?<=...) (Positivo de Retroceso)

Este lookbehind asegura que tu patrón principal sea precedido por lo que está dentro de los paréntesis (?<=...), sin incluir ese prefijo en la coincidencia. Es decir, el patrón solo coincide si es precedido por el contenido del lookbehind.

Ejemplo: Queremos extraer precios, pero solo el número, no el símbolo de moneda, asumiendo que el símbolo $ siempre precede al número.

const productos = "Camisa: $ 25.00, Pantalón: $ 45.99.";
// Patrón: Un espacio y '$' (lookbehind) seguidos de uno o más dígitos y un punto con dos dígitos.
const regexPrecios = /(?<=\$\s*)\d+\.\d{2}/g; 
const coincidencias = productos.match(regexPrecios);
console.log(coincidencias); // Resultado: ["25.00", "45.99"]
Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo: La expresión regular /(?<=\$\s*)\d+\.\d{2}/g busca números con decimales que son precios.

  • (?<=\$\s*): Este es el Lookbehind Positivo. No consume caracteres. Asegura que la posición actual sea precedida por un signo de dólar escapado (\$) seguido de cero o más espacios (\s*). Si esta condición se cumple, entonces el resto del patrón puede coincidir allí.
  • \d+\.\d{2}: Este es el patrón principal. Coincide con uno o más dígitos (\d+), seguido de un punto literal escapado (\.), y luego exactamente dos dígitos (\d{2}).

Gracias al lookbehind, la RegEx extrae solo los valores numéricos («25.00», «45.99») sin incluir el símbolo de dólar o el espacio que lo precede, ya que esos elementos están en el lookbehind y no son parte de la coincidencia final.

11.4. Lookbehind Negativo: (?<!...) (Negativo de Retroceso)11.4. Lookbehind Negativo: (?<!...) (Negativo de Retroceso)

Este lookbehind asegura que tu patrón principal NO sea precedido por lo que está dentro de los paréntesis (?<!...). Es decir, el patrón solo coincide si NO es precedido por el contenido del lookbehind.

Ejemplo: Queremos encontrar la palabra «usuario» pero solo si NO está precedida por «admin_».

const roles = "user_usuario, admin_usuario, editor_usuario";
// Patrón: La palabra "usuario" que NO esté precedida por "admin_".
const regexUsuarioNoAdmin = /(?<!admin_)usuario/g; 
const coincidencias = roles.match(regexUsuarioNoAdmin);
console.log(coincidencias); // Resultado: ["usuario", "usuario"]
Lenguaje del código: HTML, XML (xml)

Explicación del ejemplo: La expresión regular /(?<!admin_)usuario/g busca la palabra «usuario» que no tiene «admin_» justo antes.

  • (?<!admin_): Este es el Lookbehind Negativo. No consume caracteres. Asegura que la posición actual no sea precedida inmediatamente por la secuencia «admin_». Si la posición es precedida por «admin_», entonces todo el patrón falla en ese punto.
  • usuario: Este es el patrón principal que buscamos.

Por lo tanto, la RegEx encuentra «usuario» en «user_usuario» y «editor_usuario» porque no son precedidos por «admin_», pero omite el «usuario» que forma parte de «admin_usuario».

Los Lookahead y Lookbehind son herramientas avanzadas pero increíblemente útiles cuando necesitas una lógica de coincidencia muy precisa basada en el contexto que rodea a tu patrón, sin incluir ese contexto en el resultado de la coincidencia.

12. Grupos con nombre

Los grupos con nombre resuelven un problema de legibilidad y mantenimiento en tus expresiones regulares. En lugar de recordar que match[1] era el «nombre» y match[2] el «apellido», puedes asignar nombres descriptivos a tus grupos de captura.

Esto hace que tu código sea mucho más claro y menos propenso a errores, especialmente cuando la expresión regular tiene muchos grupos o si su estructura cambia con el tiempo.

Te permiten acceder a las partes capturadas de la coincidencia usando un nombre significativo en lugar de un índice numérico.

Sintaxis y acceso:

  1. Sintaxis:(?<nombre>...)
    • ?<>: Indica el inicio de un grupo con nombre.
    • nombre: Es el nombre que le asignás al grupo (debe ser un identificador de JavaScript válido).
    • ...: Es el patrón que querés que capture ese grupo.
  2. Acceso: Después de una coincidencia, puedes acceder al valor capturado a través de la propiedad match.groups.nombre.

EJEMPLO: Queremos extraer el año, mes y día de una fecha en formato YYYY-MM-DD.

const fechaString = "Hoy es 2023-10-26, mañana 2023-10-27.";
// Patrón: Capturamos el año, mes y día con nombres específicos.
const regexFecha = /(?<año>\d{4})-(?<mes>\d{2})-(?<dia>\d{2})/g;

let match;
while ((match = regexFecha.exec(fechaString)) !== null) {
    console.log(`Fecha completa: ${match[0]}`);
    console.log(`  Año: ${match.groups.año}`);   // Acceso por nombre
    console.log(`  Mes: ${match.groups.mes}`);   // Acceso por nombre
    console.log(`  Día: ${match.groups.dia}`);   // Acceso por nombre
    console.log('---');
}
/* Resultado:
Fecha completa: 2023-10-26
  Año: 2023
  Mes: 10
  Día: 26
---
Fecha completa: 2023-10-27
  Año: 2023
  Mes: 10
  Día: 27
---
*/
Lenguaje del código: JavaScript (javascript)

Explicación:

  1. const regexFecha = /(?<año>\d{4})-(?<mes>\d{2})-(?<dia>\d{2})/g;:
    • (?<año>\d{4}): Este es el primer grupo con nombre.
      • ?<año>: Le asigna el nombre «año» a este grupo.
      • \d{4}: El patrón a capturar, que son exactamente 4 dígitos (para el año).
    • -: Coincide con el guion literal.
    • (?<mes>\d{2}): El segundo grupo con nombre «mes», capturando 2 dígitos.
    • -: Coincide con el guion literal.
    • (?<dia>\d{2}): El tercer grupo con nombre «dia», capturando 2 dígitos.
    • g: La bandera global, que permite a exec() encontrar todas las fechas en la cadena.
  2. while ((match = regexFecha.exec(fechaString)) !== null): Este bucle while itera sobre cada coincidencia de fecha encontrada por la expresión regular.
  3. console.log( Año: ${match.groups.año});: Aquí es donde vemos el beneficio de los grupos con nombre. En lugar de usar un índice numérico como match[1], podemos acceder directamente al valor capturado por el grupo «año» usando match.groups.año. Esto es mucho más claro y fácil de entender de inmediato. Lo mismo aplica para match.groups.mes y match.groups.dia.

Los grupos con nombre son una mejora significativa en la usabilidad y legibilidad de las expresiones regulares en JavaScript, haciendo que el manejo de datos extraídos sea mucho más intuitivo.

13. Propiedades de unicode

Las propiedades de Unicode son una forma de clasificar y agrupar los miles de caracteres que existen más allá del alfabeto latino básico.

A diferencia de los atajos como \d (dígitos ASCII) o \w (letras, números y guion bajo ASCII), las propiedades de Unicode te permiten coincidir con caracteres basándote en sus características inherentes definidas por el estándar Unicode.

Por ejemplo, \d solo coincide con 0-9. Pero ¿qué pasa si quieres coincidir con un dígito de otro idioma, como un número árabe (٠‎, ١‎, ٢‎)? Ahí es donde entran las propiedades de Unicode.

Te permiten buscar caracteres por categorías muy específicas como:

  • Tipo general: ¿Es una letra? ¿Es un número? ¿Es un símbolo?
  • Script (escritura): ¿Es un carácter griego? ¿Cirílico? ¿Japonés?
  • Bloque: ¿Pertenece al bloque de emojis? ¿Al bloque de símbolos matemáticos?

👉\p{Propiedad}: Coincide con caracteres que tienen la propiedad especificada.

SINTAXIS:

  • \p{Propiedad}: Para coincidir con caracteres que sí tienen una propiedad Unicode específica.
  • \P{Propiedad}: Para coincidir con caracteres que NO tienen una propiedad Unicode específica, usas:

En ambos casos, es obligatorio que tu expresión regular incluya la bandera u (Unicode). Sin ella, obtendrás un error.

Por ejemplo:

  • /\p{L}/u: Coincide con cualquier letra (de cualquier idioma).
  • /\P{N}/u: Coincide con cualquier carácter que no sea un número (de cualquier sistema numérico).
  • /\p{Script=Greek}/u: Coincide con caracteres del alfabeto griego.

EJEMPLO CON \p{Propiedad}: Queremos encontrar todas las letras en un texto que podría contener caracteres de diferentes idiomas.

const textoMultilenguaje = "Hola mundo. Γεια σου κόσμε. こんにちは世界。123";
// Patrón: Coincide con cualquier carácter que sea una Letra (\p{L}), una o más veces.
const regexLetrasUnicode = /\p{L}+/gu; 
const coincidencias = textoMultilenguaje.match(regexLetrasUnicode);
console.log(coincidencias); // Resultado: ["Hola", "mundo", "Γεια", "σου", "κόσμε", "こんにちは世界"]
Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo:

  1. const textoMultilenguaje = "Hola mundo. Γεια σου κόσμε. こんにちは世界。123";: Esta cadena contiene texto en latín, griego, japonés y números.
  2. const regexLetrasUnicode = /\p{L}+/gu;: Aquí definimos la expresión regular.
    • \p{L}: Esta es la clave. \p indica una propiedad de Unicode, y {L} significa «cualquier carácter que sea una Letra». Esto incluye letras de todos los alfabetos reconocidos por Unicode (latín, griego, cirílico, japonés, etc.).
    • +: El cuantificador «una o más veces».
    • g: La bandera global, para encontrar todas las secuencias de letras.
    • u: ¡Crucial! La bandera u (Unicode) es obligatoria cuando usas propiedades de Unicode (\p{...} o \P{...}). Si la omites, obtendrás un error.

Cuando regexLetrasUnicode se aplica al texto, \p{L} coincide con «H», «o», «l», «a», luego con «m», «u», «n», «d», «o», etc. También coincide correctamente con las letras griegas (Γεια, σου, κόσμε) y las letras japonesas (こんにちは世界), ya que todas son consideradas «Letras» bajo la propiedad Unicode L. Los números «123» no son letras, por lo que no coinciden con \p{L}.

EJEMPLO CON \P{Propiedad}: Queremos encontrar todo lo que NO sean letras en el mismo texto multilenguaje.

const textoMultilenguaje = "Hola mundo. Γεια σου κόσμε. こんにちは世界。123";
// Patrón: Coincide con cualquier carácter que NO sea una Letra (\P{L}), una o más veces.
const regexNoLetrasUnicode = /\P{L}+/gu; 
const coincidencias = textoMultilenguaje.match(regexNoLetrasUnicode);
console.log(coincidencias); // Resultado: [" ", ". ", " ", ". ", " ", "。","123"]Lenguaje del código: JavaScript (javascript)

Explicación del ejemplo:

  1. const textoMultilenguaje: La misma cadena de texto de ejemplo.
  2. const regexNoLetrasUnicode = /\P{L}+/gu;:
    • \P{L}: Esta vez, \P indica «cualquier carácter que NO sea una Letra».
    • +: Una o más veces.
    • g y u: Banderas global y Unicode.

Al aplicar regexNoLetrasUnicode, la expresión regular encontrará:

  • El espacio entre «Hola» y «mundo».
  • El punto y el espacio después de «mundo».
  • Los espacios entre las palabras griegas y después de «κόσμε».
  • El punto de puntuación japonés (que no es una letra).
  • Y finalmente, la secuencia de dígitos «123», ya que los dígitos no son considerados «Letras».

Las propiedades de Unicode son invaluables cuando tus datos pueden contener texto de diferentes idiomas o símbolos especiales, permitiéndote crear patrones mucho más precisos y robustos que los atajos básicos.

14. Herramientas de pruebas de regEx online

Estas herramientas son plataformas basadas en la web que te proporcionan un entorno interactivo para construir, probar y depurar tus expresiones regulares en tiempo real.

En lugar de ejecutar tu código una y otra vez para ver si tu RegEx funciona, estas herramientas te ofrecen retroalimentación instantánea, acelerando drásticamente tu proceso de aprendizaje y desarrollo.

Aquí te presento algunas de las más populares y recomendadas:

14.1. Regex101.com (¡Altamente recomendado!)

Regex101.com es, sin duda, una de las herramientas más completas y útiles. Su característica más destacada son las explicaciones detalladas de cada componente de tu expresión regular.

  • Te permite introducir tu expresión regular, pegar tu texto de prueba y seleccionar el «sabor» de RegEx (por ejemplo, JavaScript, Python, PHP, Go, etc.). A medida que escribes, Regex101.com no solo resalta las coincidencias, sino que también desglosa tu patrón pieza por pieza, explicando qué hace cada carácter o metacaracter.

14.2. RegExr.com

RegExr.com es otra herramienta robusta y popular, con una interfaz limpia y potentes características.

  • ¿Para qué sirve? Similar a Regex101, te permite probar tus patrones contra texto de muestra. Ofrece un resaltado claro de coincidencias, una lista de grupos de captura y una biblioteca de expresiones regulares comunes.

14.3. Regexone.com

Regexone.com, a diferencia de las dos anteriores que son más para «prueba y depuración», Regexone.com se enfoca en el aprendizaje interactivo.

  • ¿Para qué sirve? Si sos principiante y querés aprender expresiones regulares desde cero, este sitio ofrece tutoriales paso a paso con ejercicios prácticos. Te presenta un concepto, te da un problema y te permite escribir y probar la RegEx directamente en el navegador.

14.4. ¿Cómo utilizarlas?

La forma de usar estas herramientas es bastante intuitiva:

✅ Ingresá tu Expresión Regular
Hay un campo dedicado para escribir o pegar tu patrón RegEx. Este es el punto de partida para probar tu expresión regular.
✅ Pegá tu Texto de Prueba
Hay otro campo grande donde colocás la cadena de texto en la que querés buscar o reemplazar. Esto permite visualizar cómo actúa tu patrón en ejemplos reales.
✅ Observá los Resultados
La herramienta resaltará automáticamente las coincidencias en tu texto. Podés ver qué partes del texto están siendo capturadas por tu RegEx.
✅ Examiná los Detalles
La mayoría de las herramientas te mostrarán información adicional, como los grupos de captura, los índices de las coincidencias y, en el caso de Regex101.com, una explicación detallada de tu patrón.
✅ Ajustá y Depurá
Modificá tu RegEx o tu texto de prueba y ve los cambios en tiempo real hasta que el patrón funcione como esperás.

Mi recomendación personal es empezar con Regex101.com por sus explicaciones didácticas.

15. Buenas prácticas y legibilidad en expresiones regulares

Así como comentamos el código JavaScript o dividimos funciones largas, también podemos aplicar principios similares a nuestras expresiones regulares para hacerlas más robustas y amigables para el futuro «yo» o para otros desarrolladores.

15.1. Comentar expresiones regulares complejas

Las expresiones regulares pueden parecer un lenguaje críptico a primera vista. Un patrón complejo, lleno de metacaracteres y cuantificadores, puede ser indescifrable sin un contexto. Comentarlas es crucial.

  • ¿Por qué es importante? Evita el «efecto WTF» (What The F***?) cuando vos o alguien más las revisen meses después. Clarifica la intención del patrón y de sus partes, especialmente si usan lookaheads/lookbehinds, grupos de captura o lógicas condicionales.
  • ¿Cómo hacerlo?
    • Comentarios en línea: Si tu lenguaje lo permite (como Python o PHP con la bandera x), podés añadir comentarios directamente dentro de la RegEx.
    • Comentarios en el código JS: Si no, usá comentarios justo antes de definir tu RegExp en JavaScript. Explicá qué valida, qué extrae y por qué ciertas partes están ahí.

Ejemplo:

// Validar un email básico:
// - Comienza con caracteres no-espacio/arroba/punto, uno o más (nombre de usuario)
// - Seguido de un '@'
// - Luego más caracteres no-espacio/arroba/punto, uno o más (dominio)
// - Seguido de un '.'
// - Termina con más caracteres no-espacio/arroba/punto, dos o más (TLD)
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;

// Otro ejemplo, simulando comentarios en RegEx si JavaScript lo permitiera (no lo hace directamente en el literal)
// En JavaScript, lo haríamos en el código
/*
const complexPasswordRegex = /
    ^                   # Inicio de la cadena
    (?=.*[a-z])         # Debe contener al menos una minúscula (Lookahead positivo)
    (?=.*[A-Z])         # Debe contener al menos una mayúscula
    (?=.*\d)            # Debe contener al menos un dígito
    (?=.*[!@#$%^&*])    # Debe contener al menos un carácter especial
    [A-Za-z\d!@#$%^&*]{8,} # Mínimo 8 caracteres, solo los permitidos
    $                   # Fin de la cadena
/x; // La bandera 'x' sería para el modo de comentario, no soportado directamente en JS literales
*/
Lenguaje del código: PHP (php)

15.2. Dividir patrones grandes en patrones más pequeños (si es posible)

A veces, una expresión regular intenta hacer demasiadas cosas. Si bien RegEx es potente, un patrón excesivamente largo y anidado se vuelve una «cadena ilegible de símbolos».

  • ¿Por qué es importante? Mejora drásticamente la legibilidad. Cada pequeña RegEx se vuelve un «bloque de construcción» con un propósito claro. Facilita la depuración: si algo falla, sabés qué parte del proceso es la que está dando problemas. También promueve la reutilización de patrones.
  • ¿Cómo hacerlo? Si tu objetivo es validar múltiples características (ej. una contraseña con diferentes criterios), podés usar múltiples test() con RegEx más pequeñas, o encadenar lógicas.

Ejemplo:

En lugar de una sola RegEx monstruosa para una contraseña:

// MAL (difícil de leer y depurar)
const passwordRegexMonstruo = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{8,}$/;

// BIEN (más legible y modular)
const password = "MyStrongP@ss1";

const hasMinLength = password.length >= 8;
const hasLowercase = /[a-z]/.test(password);
const hasUppercase = /[A-Z]/.test(password);
const hasDigit = /\d/.test(password);
const hasSpecialChar = /[!@#$%^&*]/.test(password);

if (hasMinLength && hasLowercase && hasUppercase && hasDigit && hasSpecialChar) {
    console.log("Contraseña válida");
} else {
    console.log("Contraseña inválida");
}
Lenguaje del código: JavaScript (javascript)

Explicación: En el ejemplo «BIEN», cada criterio de la contraseña se valida con su propia RegEx simple. Esto hace que sea fácil ver qué condición falla si la contraseña es inválida, y el código es mucho más fácil de entender de un vistazo.

15.3. Usar Literales cuando sea posible, new RegExp() cuando el patrón sea dinámico

JavaScript ofrece dos formas de crear expresiones regulares, y elegir la correcta es una buena práctica.

  • Literales (/patron/flags): Son la forma más común y recomendada para la mayoría de los casos.
    • ¿Por qué usarlos? Son más concisos, más rápidos (se compilan una sola vez cuando el script se carga) y no requieren escapar las barras invertidas (\) dos veces.
    • Cuándo usarlos: Cuando tu patrón es estático y no va a cambiar en tiempo de ejecución.

Ejemplo de Literal:

const texto = "Hola mundo";
const regexEstatica = /mundo/; // Patrón fijo
console.log(regexEstatica.test(texto)); // true
Lenguaje del código: JavaScript (javascript)
  • Constructor new RegExp(patronString, flagsString): Requiere una cadena de texto para el patrón y otra para las banderas.
    • ¿Por qué usarlos? Cuando el patrón o las banderas (o ambas) necesitan ser construidas dinámicamente en tiempo de ejecución, basándose en la entrada del usuario, variables u otra lógica.

Ejemplo de new RegExp() (Dinámico):

const buscar = "email"; // Esto podría venir de un input de usuario
const bandera = "i";     // O de una opción de búsqueda

// Construimos la RegEx dinámicamente
const regexDinamica = new RegExp(buscar, bandera); 

const frase = "Buscando Email en el texto.";
console.log(frase.match(regexDinamica)); // Resultado: ["Email", index: 9, input: "Buscando Email en el texto.", groups: undefined]

// Explicación: La RegEx busca la cadena "email" ignorando mayúsculas/minúsculas debido a la bandera 'i' construida dinámicamente.
Lenguaje del código: JavaScript (javascript)

Explicación: En este caso, la palabra que se busca ("email") y la bandera ("i") no se conocen de antemano y se construyen a partir de variables. new RegExp() es la única forma de crear esa expresión regular en ese momento.

Adoptar estas buenas prácticas te ayudará a escribir expresiones regulares más robustas, fáciles de entender y menos propensas a errores, lo que es invaluable en cualquier proyecto.

16. Preguntas frecuentes y resumen sobre regexp en JS.

Las expresiones regulares (RegExp) son patrones que permiten buscar, validar o reemplazar texto. Son útiles para validar emails, buscar palabras específicas, limpiar datos y manipular cadenas de forma flexible usando reglas definidas por el usuario.

Se puede usar la notación literal /patrón/ o el constructor new RegExp("patrón"). Se pueden agregar modificadores como i (ignorar mayúsculas/minúsculas) o g (global). Ejemplo: /abc/i busca «abc» sin importar el caso.

match() busca coincidencias, search() retorna la posición, replace() sustituye texto y split() divide cadenas. Todos aceptan expresiones regulares como argumento para operar dinámicamente sobre los textos.

test() devuelve true si hay coincidencia. exec() devuelve información detallada sobre la coincidencia (posición, grupos, etc.). Son útiles para validar entradas o extraer patrones de un texto de manera programática.

Las clases de caracteres definen rangos o grupos de caracteres. Se colocan entre corchetes, como [a-z] para letras minúsculas o [0-9] para dígitos. También hay clases predefinidas como \d (dígito) o \w (carácter alfanumérico).

Los cuantificadores indican cuántas veces debe aparecer un patrón. Por ejemplo, a* (cero o más), a+ (una o más), a{3} (exactamente tres veces). Permiten controlar la cantidad de repeticiones en la búsqueda.

Los grupos de captura, definidos con paréntesis (), permiten extraer subcadenas específicas de una coincidencia. Por ejemplo, /(hola) mundo/ permite acceder a «hola». Se usan con exec(), match() o replace().

Se usan patrones específicos para verificar que una cadena cumpla un formato. Ej: /^\w+@\w+\.\w+$/ valida emails simples. Podés usar test() o match() para saber si una entrada respeta el formato deseado.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *