Lección 17 · 17 de 20
Expresiones regulares · JavaScript
Analice un log en JavaScript con expresiones regulares: grupos con nombre, test, matchAll, replace con función y validación de correos.

Una expresión regular describe un patrón de texto y se escribe entre barras, como /error/i. El ejemplo analiza las líneas de un registro (log). En lineRe, ^ marca el inicio de la línea, \d{4} son cuatro dígitos, [A-Z]+ una o más mayúsculas, \s+ uno o más espacios y \w+ una palabra.
Los grupos con nombre (?<name>...) capturan cada trozo: line.match(lineRe).groups devuelve un objeto con date, time, level y user, que se desestructura directamente. Es mucho más legible que contar posiciones o encadenar split.
test() responde sí o no, y el indicador `i` no distingue mayúsculas de minúsculas. Con el indicador `g`, matchAll recorre todas las coincidencias de un texto, cada una con sus grupos: m[1] es lo que capturó el primer paréntesis, el número de pedido.
replace() admite una función que calcula cada sustitución a partir de lo capturado: aquí deja la primera letra del usuario y oculta el resto (user=l***). Para validar datos, ^ y $ obligan a que todo el texto encaje con el patrón; por eso luis@shop, sin dominio de primer nivel, no pasa la comprobación del correo.
Código · main.js
const log = [ "2024-03-01 10:15:02 INFO user=ana order=A-1001 total=59.90", "2024-03-01 10:16:45 ERROR user=luis order=A-1002 payment declined", "2024-03-01 10:20:11 INFO user=marta order=B-2001 total=120.00",];// Named groups (?<name>...) pick out each part of a line.const lineRe = /^(?<date>\d{4}-\d{2}-\d{2}) (?<time>[\d:]+) (?<level>[A-Z]+)\s+user=(?<user>\w+)/;for (const line of log) { const { time, level, user } = line.match(lineRe).groups; console.log(`${time} ${level.padEnd(5)} ${user}`);}// test() answers yes or no; the i flag ignores upper and lower case.console.log("Any errors?", log.some((line) => /error/i.test(line)));// The g flag with matchAll finds every match, with its groups.const ids = [...log.join("\n").matchAll(/order=([A-Z]-\d+)/g)].map((m) => m[1]);console.log("Orders:", ids.join(", "));// replace() with a function builds each replacement.console.log(log[1].replace(/user=(\w)\w*/, (whole, first) => `user=${first}***`));// Validating input: ^ and $ make the whole text match.const email = /^[\w.+-]+@[\w-]+\.[a-z]{2,}$/i;for (const value of ["ana@shop.es", "luis@shop", "marta.r+news@mail.com"]) { console.log(value.padEnd(22), email.test(value) ? "valid" : "invalid");}Salida · node main.js
10:15:02 INFO ana 10:16:45 ERROR luis 10:20:11 INFO marta Any errors? true Orders: A-1001, A-1002, B-2001 2024-03-01 10:16:45 ERROR user=l*** order=A-1002 payment declined ana@shop.es valid luis@shop invalid marta.r+news@mail.com valid
Para recordar
(?<name>...)captura un trozo con nombre, accesible en.groups.test()dice si hay coincidencia;iignora mayúsculas y minúsculas.- Con
g,matchAlldevuelve todas las coincidencias. replace()acepta una función para construir cada sustitución.^y$anclan el patrón al principio y al final del texto.
Ejercicio
Escriba una expresión con un grupo con nombre total que extraiga los importes de total=59.90 del log y sume todos los pedidos con matchAll.