Introducción: Las expresiones regulares en Rust — una herramienta poderosa para el procesamiento de texto
Las expresiones regulares (regex) son una parte esencial del arsenal de cualquier desarrollador que trabaje con texto. En Rust, conocido por su rendimiento y seguridad, el trabajo con expresiones regulares se implementa a través del popular crate regex. Esta biblioteca proporciona una forma rápida y confiable de buscar, extraer y reemplazar patrones de texto.
En este artículo, analizaremos en detalle cómo usar expresiones regulares en Rust: desde la instalación del crate hasta técnicas avanzadas. Aprenderá cómo verificar coincidencias, extraer datos, reemplazar texto y manejar errores. Todos los ejemplos de código están escritos en Rust y listos para usar.
1. Instalación y configuración del crate regex
Para trabajar con expresiones regulares en Rust, es necesario agregar el crate regex al archivo Cargo.toml:
[dependencies]regex = "1"Después de esto, puede importar los módulos necesarios en el código:
use regex::Regex;El crate regex compila automáticamente las expresiones regulares en un formato interno eficiente, lo que garantiza una alta velocidad de operación.
2. Operaciones básicas con regex en Rust
2.1 Verificación de coincidencia (is_match)
El método is_match devuelve true si la cadena contiene al menos una coincidencia con el patrón:
use regex::Regex;
fn main() { let re = Regex::new(r"\\d+").unwrap(); let text = "Hoy es 25 de diciembre";
if re.is_match(text) { println!("La cadena contiene números"); } else { println!("No se encontraron números"); }}Este método es útil para una validación rápida: verificar si una cadena contiene un email, teléfono u otros patrones.
2.2 Búsqueda de la primera coincidencia (find)
El método find devuelve la primera coincidencia en forma de una estructura Match, que contiene el inicio y el final de la coincidencia:
use regex::Regex;
fn main() { let re = Regex::new(r"\\b\\w+@\\w+\\.\\w+\\b").unwrap(); let text = "Mi email: user@example.com, y también admin@test.org";
if let Some(mat) = re.find(text) { println!("Email encontrado: {}", mat.as_str()); println!("Posición: {}..{}", mat.start(), mat.end()); }}Resultado de la ejecución:
Email encontrado: user@example.comPosición: 11..272.3 Búsqueda de todas las coincidencias (find_iter)
Para obtener todas las coincidencias se utiliza el iterador find_iter:
use regex::Regex;
fn main() { let re = Regex::new(r"\\d+").unwrap(); let text = "Precios: 100, 250 y 500 rublos";
for mat in re.find_iter(text) { println!("Número: {}", mat.as_str()); }}Salida:
Número: 100Número: 250Número: 5003. Extracción de grupos mediante paréntesis de captura
Una de las capacidades más potentes de regex son los grupos de captura. Permiten extraer partes de la coincidencia:
use regex::Regex;
fn main() { let re = Regex::new(r"(\\w+)@(\\w+)\\.(\\w+)").unwrap(); let text = "user@example.com";
if let Some(caps) = re.captures(text) { println!("Email completo: {}", &caps[0]); println!("Nombre de usuario: {}", &caps[1]); println!("Dominio: {}", &caps[2]); println!("Zona: {}", &caps[3]); }}Los grupos se numeran a partir del 1. El grupo 0 es toda la coincidencia completa.
También se pueden usar grupos con nombre para un código más legible:
use regex::Regex;
fn main() { let re = Regex::new(r"(?P<name>\\w+)@(?P<domain>\\w+\\.\\w+)").unwrap(); let text = "admin@test.org";
if let Some(caps) = re.captures(text) { println!("Nombre: {}", caps.name("name").unwrap().as_str