Una expresión regular es una secuencia de caracteres que forma un patrón de búsqueda. Este patrón puede ser utilizado para encontrar cadenas de texto que coincidan con ese patrón o para reemplazar texto dentro de una cadena.
Imaginad que tenéis que buscar en un texto “cualquier fecha que tenga formato DD/MM/AAAA”. Podríais hacer un bucle for con 20 if/else comprobando si hay números y barras… o podríais usar una sola línea de Regex.
En C#, las expresiones regulares se manejan mediante la clase Regex, que está incluida en el espacio de nombres System.Text.RegularExpressions.
Sintaxis básica
Antes de ir al código C#, necesitamos entender el lenguaje de los patrones. Al principio parece que alguien ha aporreado el teclado, pero tiene lógica (más o menos).
| Símbolo | Significado | Ejemplo | Coincide con |
|---|---|---|---|
. | Cualquier carácter (menos salto de línea) | a.o | ”aro”, “a1o”, “a-o” |
\d | Un dígito (0-9) | \d\d | ”05”, “99” |
\w | Alfanumérico (letras, números, _) | \w+ | ”Usuario1”, “Hola” |
^ | Inicio de la línea (Ancla) | ^Hola | Empieza por “Hola” |
$ | Fin de la línea (Ancla) | fin$ | Acaba en “fin” |
* | 0 o más veces | a* | "", “a”, “aaa” |
+ | 1 o más veces | a+ | ”a”, “aaa” (pero no "") |
? | 0 o 1 vez (Opcional) | colou?r | ”color”, “colour” |
[] | Rango o conjunto | [A-Z] | Cualquier mayúscula |
La clase Regex
En C#, la clase par regular expressions es Regex. Tenemos dos formas de usarla:
- Métodos Estáticos: Para usos rápidos y únicos (
Regex.IsMatch(...)). - Instancia: Para reutilizar el mismo patrón muchas veces (
new Regex(...)).
Validación (IsMatch)
El uso más común: ¿El texto cumple el patrón? (ej: validar un email, un DNI, un teléfono).
using System.Text.RegularExpressions;
string input = "1234A";
// Patrón: 4 dígitos seguidos de una letra mayúscula
string patron = @"^\d{4}[A-Z]$";
bool esValido = Regex.IsMatch(input, patron);
Console.WriteLine(esValido); // True
Fijaos en la @ antes del string del patrón (@"..."). Esto es un Verbatim String. Es casi obligatorio en Regex para no tener que escapar cada barra invertida (\) dos veces.
Extracción de datos (Match y Groups)
Aquí es donde Regex tiene mayor utilidad. No solo validamos, sino que sacamos información del texto.
Imaginad que tenemos un log: "Error en el sistema: [Código 500] - Timeout". Queremos sacar el número de error.
string texto = "Error en el sistema: [Código 500] - Timeout";
string patron = @"\[Código (\d+)\]"; // Los paréntesis () crean un GRUPO
Match coincidencia = Regex.Match(texto, patron);
if (coincidencia.Success)
{
// Group[0] es toda la coincidencia: "[Código 500]"
// Group[1] es lo de dentro del paréntesis: "500"
string codigo = coincidencia.Groups[1].Value;
Console.WriteLine($"El error es: {codigo}");
}
Búsqueda múltiple (Matches)
Si esperamos encontrar el patrón varias veces en el mismo texto (ej: buscar todos los emails en un documento).
string texto = "Contacta con [email protected] o con [email protected]";
string patron = @"\w+@\w+\.com";
MatchCollection resultados = Regex.Matches(texto, patron);
foreach (Match m in resultados)
{
Console.WriteLine($"Email encontrado: {m.Value}");
}
Reemplazo y limpieza (Replace)
Podemos usar Regex para hacer un “Buscar y Reemplazar” inteligente.
string telefonoSucio = "(+34) 666-55-44";
// Queremos dejar solo los números.
// \D significa "Todo lo que NO sea un dígito"
string soloNumeros = Regex.Replace(telefonoSucio, @"\D", "");
Console.WriteLine(soloNumeros); // "346665544"
También podemos usarlo para ocultar datos sensibles:
string tarjeta = "1234-5678-9012-3456";
// Reemplaza los primeros 12 dígitos por X
string oculta = Regex.Replace(tarjeta, @"^\d{4}-\d{4}-\d{4}", "XXXX-XXXX-XXXX");
Rendimiento y optimización
Regex es potente, pero lento si se usa mal. El motor de Regex tiene que compilar el patrón a un código interno antes de ejecutarlo.
Si tenéis un patrón complejo que vais a usar millones de veces dentro de un bucle, podéis compilarlo con RegexOptions.Compiled.
// Tarda más en crearse (new), pero es más rápido al ejecutarse (IsMatch)
Regex regexCompilada = new Regex(@"^\d+$", RegexOptions.Compiled);
No uséis Compiled para todo. La compilación consume CPU y memoria inicial. Usadlo solo para expresiones estáticas muy reutilizadas.
