TOC

This article is currently in the process of being translated into Spanish (~99% done).

Regular Expressions (Regex):

Search/Replace with the Regex Class

Ya hemos discutido la clase Regex y como usarla cuando queremos buscar a través de una cadena en el artículo previo. Las Expresiones Regulares son excelentes para eso, pero otro caso de uso es cuando quiera llevar a cabo operaciones de búsqueda/reemplazo, donde usted quiere buscar un patrón específico y reemplazarlo con otra cosa. La clase String ya tiene el método Replace(), pero este sólo es bueno para hacer búsquedas simples. Cuando usa Expresiones Regulares, puede usar el poder de las búsquedas regex y usar los grupos capturados como parte de la cadena de reemplazo. ¿Suena complicado? No se preocupe, empezaremos con un ejemplo simple y luego lentamente trabajaremos hacia casos más avanzados.

Como en el artículo previo, todos los ejemplos asumen que ha importado el espacio de nombre RegularExpressions, como esto:

using System.Text.RegularExpressions;

Hecho esto, tratemos de trabajar con reemplazo de cadenas basado en Expresiones Regulares. Usaremos el método Replace encontrado en la clase Regex:

string testString = "<b>Hello, <i>world</i></b>";
Regex regex = new Regex("<[^>]+>");
string cleanString = regex.Replace(testString, "");
Console.WriteLine(cleanString);

Este ejemplo muestra una aproximación simplificada para remover etiquetas HTML de una cadena. Buscamos cualquier cosa rodeada de un par de corchetes angulares (<>) y luego usamos el métod Replace() para reemplazar la ocurrencia con una cadena vacía, básicamente removemos las etiquetas HTML de la cadena de prueba.

Reemplazo de Valores Capturados

Pero digamos que no quiere removerlos en realidad, sino en vez de eso quiere transformar las etiquetas en algo que no será interpretado por un navegador, por ejemplo, reemplazar los corchetes angulares (<>) con corchetes cuadrados([]). Esto es donde las Expresiones Regulares muestran su poder, por que realmente es muy fácil, como se ilustra por la versión ligeramente reescrita de nuestro ejemplo previo:

string testString = "<b>Hello, <i>world</i></b>";
Regex regex = new Regex("<([^>]+)>");
string cleanString = regex.Replace(testString, "[$1]");
Console.WriteLine(cleanString);

En realidad sólo cambié dos detalles menores: Agregué un par de paréntesis a la regex, para crear un grupo de captura, esencialmente capturando el valor entre los corchetes angulares dentro del primer grupo de captura. En el método Replace() hice referencia a esto usando la notación especial $1, la cual básicamente se refiere al grupo de captura número 1. Con esto, nuestra salida ahora se verá como:

[b]Hello, [i]world[/i][/b]

Grupos de Captura Nombrados

Puede por supuesto hacer lo mismo cuando usa grupos de captura nombrados (discutidos en el artículo previo), como esto:

string testString = "<b>Hello, <i>world</i></b>";
Regex regex = new Regex("<(?<tagName>[^>]+)>");
string cleanString = regex.Replace(testString, "[${tagName}]");
Console.WriteLine(cleanString);

Cuando use grupos de captura nombrados, sólo utilice la notación ${nombre-del-grupo-de-captura}.

Usando un método MatchEvaluator

¿Pero y si queremos aún más control sobre cómo es reemplazado el valor? Podemos usar un parámetro MatchEvaluator para esto - es básicamnete una referencia (delegada) a un método el cual será llamado cada vez que un reemplazo se vaya a realizar, permitiendole modifiar el valor de reemplazo antes de usarlo. Mantengamos el ejemplo de etiquetas HTML que ya usamos un par de veces, pero esta vez, tomemos control sobre cuales etiquetas HTML son usadas. Aquí esta el ejemplo completo:

using System;
using System.Text.RegularExpressions;

namespace RegexSearchReplaceMethod
{
    class Program
    {
static void Main(string[] args)
{
    string testString = "<b>Hello, <i>world</i></b>";
    Regex regex = new Regex("<(?<tagName>[^>]+)>");
    string cleanString = regex.Replace(testString, ProcessHtmlTag);
    Console.WriteLine(cleanString);
}

private static string ProcessHtmlTag(Match m)
{
    string tagName = m.Groups["tagName"].Value;
    string endTagPrefix = "";
    if(tagName.StartsWith("/"))
    {
endTagPrefix = "/";
tagName = tagName.Substring(1);
    }
    switch (tagName)
    {
case "b":
    tagName = "strong";
    break;
case "i":
    tagName = "em";
    break;
    }
    return "<" + endTagPrefix + tagName.ToLower() + ">";
}
    }
}

La primer parte del ejemplo se ve exactamente igual que antes, excepto que en vez de proveer una cadena de reemplazo, pasamos una referencia a nuestro método ProcessHtmlTag(). Como se mencionó, este método es llamado cada vez que un reemplazo está por realizarse, con la coincidencia en cuestión como un parámetro. Esto significa que en nuestro método MatchEvaluator, tenemos toda la información acerca de la coincidencia de tal modo que podemos actuar acordemente. En este caso, usamos esta oportunidad para hacer las etiquetas más semánticas al reemplazar la etiqueta negrita (b) con una etiqueta fuerte (strong) y la etiqueta itálica (i) con una etiqueta énfasis (em). No importa si la etiqueta es reemplazada o no, convertimos el texto en minúsculas.

Usando un parámetro MatchEvaluator es evidentemente muy poderodo y esto es sólo un ejemplo simple de lo que puede lograrse.

Resumen

Las operaciones de búsqueda/reemplazo se hacen muy poderosas cuando usa Expresiones Regulares y aún más cuando usa el parámetro MatchEvaluator, donde las posibilidades de manipulación de cadenas llegan a ser casí infinitas.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!