Saltar al contenido principal

Regex

Las expresiones regulares (regex) son herramientas poderosas para la coincidencia de patrones y la manipulación de texto. Así es como los diferentes lenguajes manejan las operaciones con regex.

Coincidencia de Patrones Básica​

// Create regex
const pattern = /hello/i; // literal with flag
const pattern2 = new RegExp("hello", "i"); // constructor

// Test match
pattern.test("Hello World"); // true

// Find match
"Hello World".match(/hello/i); // ["Hello"]
"Hello World".search(/hello/i); // 0 (index)

// Find all matches
"hello hello".match(/hello/g); // ["hello", "hello"]

Operaciones de Reemplazo​

// Replace first match
"Hello World".replace(/hello/i, "Hi"); // "Hi World"

// Replace all matches
"hello hello".replace(/hello/g, "Hi"); // "Hi Hi"

// Replace with function
"hello world".replace(/\w+/g, (match) => match.toUpperCase()); // "HELLO WORLD"

Grupos de Captura​

// Capture groups
const match = "John Doe".match(/(w+) (w+)/);
// match[0] = "John Doe"
// match[1] = "John"
// match[2] = "Doe"

// Named groups (ES2018+)
const named = /(?<first>w+) (?<last>w+)/.exec("John Doe");
named.groups.first; // "John"
named.groups.last; // "Doe"

// Use in replace
"John Doe".replace(/(w+) (w+)/, "$2, $1"); // "Doe, John"

Patrones Comunes​

// Email
/^[\w\.-]+@[\w\.-]+\.[a-z]{2,}$/i

// Phone (US)
/^\+?1?[-. ]?\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/

// URL
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/

// Digits only
/^\d+$/

// Alphanumeric
/^[a-zA-Z0-9]+$/

Puntos Clave​

  • Soporte incorporado vs bibliotecas — JavaScript (/pattern/ o new RegExp), Python (módulo re), Ruby (/pattern/), Java (Pattern/Matcher), C# (Regex), C++ (<regex>) y Go (regexp) incluyen regex en la biblioteca estándar. C requiere regex.h POSIX o una biblioteca como PCRE; Zig no tiene regex incorporado y típicamente usa bibliotecas externas; Rust necesita el crate regex. Si estás construyendo un proyecto que usa intensivamente coincidencia de patrones, prefiere un lenguaje con soporte incorporado; para trabajo en sistemas o embebidos, ten en cuenta las dependencias de bibliotecas.

  • Variaciones de sintaxis — La mayoría de los lenguajes usan patrones estilo PCRE. JavaScript y Ruby permiten sintaxis literal: /hello/i para insensible a mayúsculas. Go y Rust usan patrones basados en strings: Regex::new(r"(?i)hello") en Rust o regexp.Compile("(?i)hello") en Go. Las operaciones de reemplazo también difieren: "hello hello".gsub(/hello/, "Hi") en Ruby vs re.sub(r"hello", "Hi", text) en Python. Al portar regex entre lenguajes, presta atención a las diferencias de escape—especialmente en literales de string donde las barras invertidas pueden necesitar duplicarse.

  • Grupos de captura — Los grupos con nombre (?<first>\w+) (?<last>\w+) son soportados en JavaScript, PHP, Rust, Python, C#, Java y Ruby, dando acceso limpio como match.groups.first o caps["first"]. El regex POSIX de C proporciona regmatch_t para grupos posicionales pero no grupos con nombre; el NSRegularExpression de Swift expone rangos por índice, requiriendo extracción manual. Para parsear texto estructurado (por ejemplo, líneas de log, archivos de configuración), prefiere un lenguaje con soporte de grupos con nombre para mantener el código legible.

  • Ergonomía de la API — Ruby y JavaScript ofrecen la sintaxis más concisa: "Hello World" =~ /hello/i retorna el índice de coincidencia; "hello hello".gsub(/hello/, "Hi") hace reemplazo total en una línea. C, C++ y Swift requieren más código repetitivo: abrir archivos, iterar con sregex_iterator, convertir NSRange a índices de String. Para procesamiento rápido de texto y scripting, elige Ruby, Python o JavaScript; para código crítico en rendimiento o de bajo nivel, acepta la verbosidad de C/C++ o las APIs explícitas de Rust y Go.