Usar expresiones regulares para extraer parte de un texto

ExtractingTextUsingRegex_RenatoGroffe

Enlaces: Lenguaje de expresiones regulares

Ejemplo 1:

string text = "x=3.452 y=4521 z= 3412";  
string[] results = text.ExtractStringsUsingRegex(@"\d+(?:\.\d+)?");

Ejemplo 2:

text = "To contact send an email to test@acme.com. If you don't get " + 
    "a quick response , please send an e- mail  answers@acme.com.br."; 
results = text.ExtractStringsUsingRegex("[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})"); 

Los métodos IsValidEmail y DomainMapper pueden estar incluidos en una biblioteca de métodos de la utilidad de expresiones regulares o pueden incluirse como métodos estáticos o de instancia privados en la clase de aplicación.

Expresión Regular para IsValidEmail: ^(?(“)(“.+?(?<!\\)”@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&’\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))”(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$

Ejemplo 3: El patrón de expresión regular (Mr\.? |Mrs\.? |Miss |Ms\.? ) busca coincidencias con cualquier aparición de “Mr “, “Mr. ” , “Mrs “, “Mrs. ” , “Miss “, “Ms o “Ms. ” . La llamada al método Regex.Replace reemplaza la cadena coincidente con String.Empty; es decir, la quita de la cadena original.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = "(Mr\\.? |Mrs\\.? |Miss |Ms\\.? )";
      string[] names = { "Mr. Henry Hunt", "Ms. Sara Samuels", 
                         "Abraham Adams", "Ms. Nicole Norris" };
      foreach (string name in names)
         Console.WriteLine(Regex.Replace(name, pattern, String.Empty));
   }
}
// The example displays the following output:
//    Henry Hunt
//    Sara Samuels
//    Abraham Adams
//    Nicole Norris

Ejemplo 4: Duplicar palabras accidentalmente es un error frecuente que cometen los escritores. Se puede usar una expresión regular para identificar palabras duplicadas, como se muestra en el ejemplo siguiente.

using System;
using System.Text.RegularExpressions;

public class Class1
{
   public static void Main()
   {
      string pattern = @"\b(\w+?)\s\1\b";
      string input = "This this is a nice day. What about this? This tastes good. I saw a a dog.";
      foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
         Console.WriteLine("{0} (duplicates '{1}') at position {2}", 
                           match.Value, match.Groups[1].Value, match.Index);
   }
}
// The example displays the following output:
//       This this (duplicates 'This)' at position 0
//       a a (duplicates 'a)' at position 66

El patrón de expresión regular \b(\w+?)\s\1\b se puede interpretar de la manera siguiente:
\b: Empieza en un límite de palabras.
(\w+?): Coincide con uno o más caracteres de palabra, pero con el menor número de caracteres posible. Juntos, forman un grupo al que se puede hacer referencia como \1.
\s: Coincide con un carácter de espacio en blanco.
\1: Coincide con la subcadena que es igual al grupo denominado \1.
\b: Coincide con un límite de palabras.

Ejemplo 5: En el ejemplo siguiente se muestra la eficacia de las expresiones regulares, además de la flexibilidad que ofrecen las características de globalización de .NET Framework. Se usa el objeto NumberFormatInfo para determinar el formato de los valores de divisa en la referencia cultural actual del sistema. A continuación, se usa dicha información para construir dinámicamente una expresión regular que extrae los valores de divisa del texto. Para cada coincidencia, se extrae el subgrupo que solo contiene la cadena numérica, se convierte el subgrupo en un valor Decimal y se calcula un total acumulativo.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      // Define text to be parsed.
      string input = "Office expenses on 2/13/2008:\n" + 
                     "Paper (500 sheets)                      $3.95\n" + 
                     "Pencils (box of 10)                     $1.00\n" + 
                     "Pens (box of 10)                        $4.49\n" + 
                     "Erasers                                 $2.19\n" + 
                     "Ink jet printer                        $69.95\n\n" + 
                     "Total Expenses                        $ 81.58\n"; 

      // Get current culture's NumberFormatInfo object.
      NumberFormatInfo nfi = CultureInfo.CurrentCulture.NumberFormat;
      // Assign needed property values to variables.
      string currencySymbol = nfi.CurrencySymbol;
      bool symbolPrecedesIfPositive = nfi.CurrencyPositivePattern % 2 == 0;
      string groupSeparator = nfi.CurrencyGroupSeparator;
      string decimalSeparator = nfi.CurrencyDecimalSeparator;

      // Form regular expression pattern.
      string pattern = Regex.Escape( symbolPrecedesIfPositive ? currencySymbol : "") + 
                       @"\s*[-+]?" + "([0-9]{0,3}(" + groupSeparator + "[0-9]{3})*(" + 
                       Regex.Escape(decimalSeparator) + "[0-9]+)?)" + 
                       (! symbolPrecedesIfPositive ? currencySymbol : ""); 
      Console.WriteLine( "The regular expression pattern is:");
      Console.WriteLine("   " + pattern);      

      // Get text that matches regular expression pattern.
      MatchCollection matches = Regex.Matches(input, pattern, 
                                              RegexOptions.IgnorePatternWhitespace);               
      Console.WriteLine("Found {0} matches.", matches.Count); 

      // Get numeric string, convert it to a value, and add it to List object.
      List expenses = new List();

      foreach (Match match in matches)
         expenses.Add(Decimal.Parse(match.Groups[1].Value));      

      // Determine whether total is present and if present, whether it is correct.
      decimal total = 0;
      foreach (decimal value in expenses)
         total += value;

      if (total / 2 == expenses[expenses.Count - 1]) 
         Console.WriteLine("The expenses total {0:C2}.", expenses[expenses.Count - 1]);
      else
         Console.WriteLine("The expenses total {0:C2}.", total);
   }  
}
// The example displays the following output:
//       The regular expression pattern is:
//          \$\s*[-+]?([0-9]{0,3}(,[0-9]{3})*\.?[0-9]+)
//       Found 6 matches.
//       The expenses total $81.58.

Ejemplo 6: Buscar enlaces a páginas web

private static void DumpHRefs(string inputString) 
{
   Match m;
   string HRefPattern = "href\\s*=\\s*(?:[\"'](?[^\"']*)[\"']|(?\\S+))";

   try {
      m = Regex.Match(inputString, HRefPattern, 
                      RegexOptions.IgnoreCase | RegexOptions.Compiled, 
                      TimeSpan.FromSeconds(1));
      while (m.Success)
      {
         Console.WriteLine("Found href " + m.Groups[1] + " at " 
            + m.Groups[1].Index);
         m = m.NextMatch();
      }   
   }
   catch (RegexMatchTimeoutException) {
      Console.WriteLine("The matching operation timed out.");
   }
}

href: Busca coincidencias con la cadena literal “href”. La búsqueda no distingue entre mayúsculas y minúsculas.
\s*: Busca coincidencias con cero o más caracteres de espacio en blanco.
=: Busca coincidencias con el signo de igualdad.
\s*: Busca coincidencias con cero o más caracteres de espacio en blanco.
(?:[“‘](?[^”‘]*)”|(?\S+)): Busca coincidencias con uno de los siguientes elementos sin asignar el resultado a un grupo capturado:

  1. Una comilla o apóstrofo, seguido de cero o más apariciones de cualquier carácter que no sea una comilla o un apóstrofo, seguido por una comilla o un apóstrofo. Este modelo incluye el grupo denominado 1.
  2. Uno o más caracteres que no sean un espacio en blanco. Este modelo incluye el grupo denominado 1.

(?[^”‘]*): Asigna cero o más apariciones de cualquier carácter distinto de una comilla o un apóstrofo al grupo de captura denominado 1.
“(?\S+): Asigna uno o más caracteres que no sean un espacio en blanco al grupo de captura denominado 1.

Ejemplo 7: El ejemplo de código siguiente se utiliza el método de Regex.Replace para reemplazar fechas con el formato mm/dd/yy por fechas con el formato dd-mm-yy.

static string MDYToDMY(string input) 
{
   try {
      return Regex.Replace(input, 
            "\\b(?\\d{1,2})/(?\\d{1,2})/(?\\d{2,4})\\b",
            "${day}-${month}-${year}", RegexOptions.None,
            TimeSpan.FromMilliseconds(150));
   }         
   catch (RegexMatchTimeoutException) {
      return input;
   }
}
using System;
using System.Globalization;
using System.Text.RegularExpressions;

public class Class1
{
   public static void Main()
   {
      string dateString = DateTime.Today.ToString("d", 
                                        DateTimeFormatInfo.InvariantInfo);
      string resultString = MDYToDMY(dateString);
      Console.WriteLine("Converted {0} to {1}.", dateString, resultString);
   }

   static string MDYToDMY(string input) 
   {
      try {
         return Regex.Replace(input, 
               "\\b(?\\d{1,2})/(?\\d{1,2})/(?\\d{2,4})\\b",
               "${day}-${month}-${year}", RegexOptions.None,
               TimeSpan.FromMilliseconds(150));
      }         
      catch (RegexMatchTimeoutException) {
         return input;
      }
   }

}
// The example displays the following output to the console if run on 8/21/2007:
//      Converted 08/21/2007 to 21-08-2007.

\b: Comienza la búsqueda de coincidencias en un límite de palabras.
(?\d{1,2}): Buscar coincidencias con uno o dos dígitos decimales. Éste es el grupo capturado month.
/: Buscar coincidencias con una barra diagonal.
(?\d{1,2}): Buscar coincidencias con uno o dos dígitos decimales. Este es el grupo capturado day.
/: Buscar coincidencias con una barra diagonal.
(?\d{2,4}): Busca coincidencias con dos a cuatro dígitos decimales. Este es el grupo capturado year.
\b: Finaliza la búsqueda de coincidencias en un límite de palabras.

$(day): Agregar la cadena capturada por el grupo de captura day.
: Agregar un guión.
$(month): Agregar la cadena capturada por el grupo de captura month.
: Agregar un guión.
$(year): Agregar la cadena capturada por el grupo de captura year.

Ejemplo 8: Puede utilizar el método CleanInput definido en este ejemplo para quitar caracteres potencialmente dañinos especificados en un campo de texto que acepta datos proporcionados por el usuario. En este caso, CleanInput quita todos los caracteres no alfanuméricos excepto los puntos (.), los símbolos de arroba (@) y los guiones (-), y devuelve la cadena restante. Sin embargo, puede modificar el patrón de expresión regular para que quite cualquier carácter que no deba incluirse en una cadena de entrada.

using System;
using System.Text.RegularExpressions;

public class Example
{
    static string CleanInput(string strIn)
    {
        // Replace invalid characters with empty strings.
        try {
           return Regex.Replace(strIn, @"[^\w\.@-]", "", 
                                RegexOptions.None, TimeSpan.FromSeconds(1.5)); 
        }
        // If we timeout when replacing invalid characters, 
        // we should return Empty.
        catch (RegexMatchTimeoutException) {
           return String.Empty;   
        }
    }
}

El modelo de expresión regular [^\w\.@-] coincide con cualquier carácter que no sea un carácter alfabético, un punto, un símbolo @ o un guión. Un carácter alfabético es cualquier letra, dígito decimal o conector de puntuación como un subrayado. Cualquier carácter que coincida con este modelo es reemplazado por String.Empty, que es la cadena definida por el modelo de reemplazo. Para permitir caracteres adicionales en los datos proporcionados por el usuario, agregue esos caracteres a la clase de caracteres en el patrón de expresión regular. Por ejemplo, el patrón de expresión regular [^\w\.@-\\%] también permite un símbolo de porcentaje y una barra diagonal inversa en una cadena de entrada.

Ejemplo 9: En el ejemplo se usa el método Match.Result para devolver el protocolo seguido por un signo de dos puntos y seguido a su vez por el número de puerto.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string url = "http://www.contoso.com:8080/letters/readme.html";

      Regex r = new Regex(@"^(?\w+)://[^/]+?(?:\d+)?/",
                          RegexOptions.None, TimeSpan.FromMilliseconds(150));
      Match m = r.Match(url);
      if (m.Success)
         Console.WriteLine(r.Match(url).Result("${proto}${port}")); 
   }
}
// The example displays the following output:
//       http:8080

^: Comenzar la búsqueda de coincidencia al principio de la cadena.
(?\w+): Coincide con uno o varios caracteres que se usan para formar palabras. Denominar a este grupo proto.
://: Buscar una coincidencia con un signo dos puntos seguido por dos barras diagonales.
[^/]+?: Buscar una coincidencia con una o más apariciones (pero las mínimas posibles) de cualquier carácter distinto de una barra diagonal.
(?:\d+)?: Buscar una coincidencia con cero o una aparición de un signo de dos puntos seguida por uno o más caracteres de dígito. Denominar a este grupo port.
/: Buscar una coincidencia con una barra diagonal.