DMarlon Studio

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.

JavaScript · Expresiones regulares en DMarlon Studio: el código del ejemplo y su salida en la terminal

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; i ignora mayúsculas y minúsculas.
  • Con g, matchAll devuelve 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.