Clase System.Text.RegularExpressions.Regex

En este artículo se proporcionan comentarios adicionales a la documentación de referencia de esta API.

La Regex clase representa . Motor de expresiones regulares de NET. Puede usar esta clase para:

  • Analiza rápidamente grandes cantidades de texto para buscar patrones de caracteres específicos.
  • Extraer, editar, reemplazar o eliminar subcadenas de texto.
  • Agregue las cadenas extraídas a una colección para generar un informe.

Nota:

Si desea validar una cadena mediante la determinación de si se ajusta a un patrón de expresión regular determinado, puede usar la System.Configuration.RegexStringValidator clase .

Para usar expresiones regulares, defina el patrón que desea identificar en una secuencia de texto mediante la sintaxis documentada en lenguaje de expresiones regulares: referencia rápida. A continuación, puede crear instancias de un Regex objeto opcionalmente. Por último, se llama a un método que realiza alguna operación, como reemplazar texto que coincida con el patrón de expresión regular o identificar una coincidencia de patrón.

Para obtener más información sobre el lenguaje de expresiones regulares, vea Lenguaje de expresiones regulares: referencia rápida o descarga e impresión de uno de estos folletos:

Referencia rápida en formatoDe word (.docx) Referencia rápida en formato PDF (.pdf)

Métodos Regex frente a String

La System.String clase incluye varios métodos de búsqueda y comparación que puede usar para realizar la coincidencia de patrones con texto. Por ejemplo, los String.Containsmétodos , String.EndsWithy String.StartsWith determinan si una instancia de cadena contiene una subcadena especificada; y los String.IndexOfmétodos , String.IndexOfAny, String.LastIndexOfy String.LastIndexOfAny devuelven la posición inicial de una subcadena especificada en una cadena. Use los métodos de la System.String clase cuando busque una cadena específica. Use la Regex clase cuando busque un patrón específico en una cadena. Para obtener más información y ejemplos, vea Expresiones regulares de .NET.

Métodos estáticos frente a instancias

Después de definir un patrón de expresión regular, puede proporcionarlo al motor de expresiones regulares de dos maneras:

  • Creando una instancia de un Regex objeto que representa la expresión regular. Para ello, pase el patrón de expresión regular a un Regex constructor. Un Regex objeto es inmutable; cuando se crea una instancia de un Regex objeto con una expresión regular, no se puede cambiar la expresión regular de ese objeto.

  • Al proporcionar la expresión regular y el texto para buscar en un static método (Shared en Visual Basic). Regex Esto le permite usar una expresión regular sin crear explícitamente un Regex objeto .

Todos los Regex métodos de identificación de patrones incluyen sobrecargas estáticas e de instancia.

El motor de expresiones regulares debe compilar un patrón determinado para poder usar el patrón. Dado que Regex los objetos son inmutables, se trata de un procedimiento único que se produce cuando se llama a un Regex constructor de clase o a un método estático. Para eliminar la necesidad de compilar repetidamente una sola expresión regular, el motor de expresiones regulares almacena en caché las expresiones regulares compiladas que se usan en las llamadas de método estático. Como resultado, los métodos de coincidencia de patrones de expresión regular ofrecen un rendimiento comparable para los métodos estáticos e de instancia. Sin embargo, el almacenamiento en caché puede afectar negativamente al rendimiento en los dos casos siguientes:

  • Cuando se usan llamadas a métodos estáticos con un gran número de expresiones regulares. De forma predeterminada, el motor de expresiones regulares almacena en caché las 15 expresiones regulares estáticas usadas más recientemente. Si la aplicación usa más de 15 expresiones regulares estáticas, se deben volver a compilar algunas expresiones regulares. Para evitar esta recompilación, puede aumentar la Regex.CacheSize propiedad .

  • Al crear instancias de nuevos Regex objetos con expresiones regulares que se han compilado anteriormente. Por ejemplo, el código siguiente define una expresión regular para buscar palabras duplicadas en una secuencia de texto. Aunque en el ejemplo se usa una sola expresión regular, se crea una instancia de un nuevo Regex objeto para procesar cada línea de texto. Esto da como resultado la recompilación de la expresión regular con cada iteración del bucle.

    StreamReader sr = new StreamReader(filename);
    string input;
    string pattern = @"\b(\w+)\s\1\b";
    while (sr.Peek() >= 0)
    {
       input = sr.ReadLine();
       Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);
       MatchCollection matches = rgx.Matches(input);
       if (matches.Count > 0)
       {
          Console.WriteLine("{0} ({1} matches):", input, matches.Count);
          foreach (Match match in matches)
             Console.WriteLine("   " + match.Value);
       }
    }
    sr.Close();
    
    Dim sr As New StreamReader(filename)
    Dim input As String
    Dim pattern As String = "\b(\w+)\s\1\b"
    Do While sr.Peek() >= 0
       input = sr.ReadLine()
       Dim rgx As New Regex(pattern, RegexOptions.IgnoreCase)
       Dim matches As MatchCollection = rgx.Matches(input)
       If matches.Count > 0 Then
          Console.WriteLine("{0} ({1} matches):", input, matches.Count)
          For Each match As Match In matches
             Console.WriteLine("   " + match.Value)
          Next   
       End If
    Loop
    sr.Close()
    

    Para evitar la recompilación, debe crear una instancia de un único Regex objeto accesible para todo el código que lo requiera, como se muestra en el ejemplo reescrito siguiente.

    StreamReader sr = new StreamReader(filename);
    string input;
    string pattern = @"\b(\w+)\s\1\b";
    Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);
    
    while (sr.Peek() >= 0)
    {
       input = sr.ReadLine();
       MatchCollection matches = rgx.Matches(input);
       if (matches.Count > 0)
       {
          Console.WriteLine("{0} ({1} matches):", input, matches.Count);
          foreach (Match match in matches)
             Console.WriteLine("   " + match.Value);
       }
    }
    sr.Close();
    
    Dim sr As New StreamReader(filename)
    Dim input As String
    Dim pattern As String = "\b(\w+)\s\1\b"
    Dim rgx As New Regex(pattern, RegexOptions.IgnoreCase)
    Do While sr.Peek() >= 0
       input = sr.ReadLine()
       Dim matches As MatchCollection = rgx.Matches(input)
       If matches.Count > 0 Then
          Console.WriteLine("{0} ({1} matches):", input, matches.Count)
          For Each match As Match In matches
             Console.WriteLine("   " + match.Value)
          Next   
       End If
    Loop
    sr.Close()
    

Realizar operaciones de expresión regular

Tanto si decide crear instancias de un Regex objeto como llamar a sus métodos o llamar a métodos estáticos, la Regex clase ofrece la siguiente funcionalidad de coincidencia de patrones:

  • Validación de una coincidencia. Llame al IsMatch método para determinar si hay una coincidencia.

  • Recuperación de una sola coincidencia. Se llama al Match método para recuperar un Match objeto que representa la primera coincidencia en una cadena o en parte de una cadena. Las coincidencias posteriores se pueden recuperar llamando al Match.NextMatch método .

  • Recuperación de todas las coincidencias. Llama al Matches método para recuperar un System.Text.RegularExpressions.MatchCollection objeto que representa todas las coincidencias encontradas en una cadena o en parte de una cadena.

  • Reemplazo del texto coincidente. Llame al método para reemplazar el Replace texto coincidente. El texto de reemplazo también se puede definir mediante una expresión regular. Además, algunos de los Replace métodos incluyen un MatchEvaluator parámetro que permite definir mediante programación el texto de reemplazo.

  • Creación de una matriz de cadenas formada a partir de partes de una cadena de entrada. Llame al Split método para dividir una cadena de entrada en las posiciones definidas por la expresión regular.

Además de sus métodos de coincidencia de patrones, la Regex clase incluye varios métodos de propósito especial:

  • El Escape método escapa a los caracteres que se pueden interpretar como operadores de expresión regular en una expresión regular o una cadena de entrada.
  • El Unescape método quita estos caracteres de escape.
  • El CompileToAssembly método crea un ensamblado que contiene expresiones regulares predefinidas. .NET contiene ejemplos de estos ensamblados de propósito especial en el System.Web.RegularExpressions espacio de nombres .

Definición de un valor de tiempo de espera

.NET admite un lenguaje de expresiones regulares completo que proporciona una gran potencia y flexibilidad en la coincidencia de patrones. Sin embargo, la potencia y la flexibilidad tienen un costo: el riesgo de un rendimiento deficiente. Las expresiones regulares que funcionan mal son sorprendentemente fáciles de crear. En algunos casos, las operaciones de expresiones regulares que dependen de un retroceso excesivo pueden parecer dejar de responder cuando procesan texto que casi coincide con el patrón de expresión regular. Para obtener más información sobre el motor de expresiones regulares de .NET, vea Detalles del comportamiento de expresiones regulares. Para obtener más información sobre el retroceso excesivo, consulte Retroceso.

A partir de .NET Framework 4.5, puede definir un intervalo de tiempo de espera para que las coincidencias de expresiones regulares limiten el retroceso excesivo. Según el patrón de expresión regular y el texto de entrada, el tiempo de ejecución puede superar el intervalo de tiempo de espera especificado, pero no pasará más tiempo de retroceso que el intervalo de tiempo de espera especificado. Si el motor de expresiones regulares agota el tiempo de espera, produce una RegexMatchTimeoutException excepción. En la mayoría de los casos, esto impide que el motor de expresiones regulares desperdicia la potencia de procesamiento intentando buscar coincidencias con texto que casi coincida con el patrón de expresión regular. Sin embargo, también podría indicar que el intervalo de tiempo de espera se ha establecido demasiado bajo o que la carga de la máquina actual ha provocado una degradación general del rendimiento.

La forma de controlar la excepción depende de la causa de la excepción. Si se produce la excepción porque el intervalo de tiempo de espera se establece demasiado bajo o debido a una carga excesiva de la máquina, puede aumentar el intervalo de tiempo de espera y volver a intentar la operación coincidente. Si se produce la excepción porque la expresión regular se basa en un retroceso excesivo, puede suponer que una coincidencia no existe y, opcionalmente, puede registrar información que le ayudará a modificar el patrón de expresión regular.

Puede establecer un intervalo de tiempo de espera llamando al Regex(String, RegexOptions, TimeSpan) constructor al crear una instancia de un objeto de expresión regular. Para los métodos estáticos, puede establecer un intervalo de tiempo de espera llamando a una sobrecarga de un método coincidente que tiene un matchTimeout parámetro . Si no establece explícitamente un valor de tiempo de espera, el valor de tiempo de espera predeterminado se determina de la siguiente manera:

  • Mediante el uso del valor de tiempo de espera de toda la aplicación, si existe uno. Establezca el valor de tiempo de espera de toda la aplicación llamando al AppDomain.SetData método para asignar la representación de cadena de un TimeSpan valor a la REGEX_DEFAULT_MATCH_TIMEOUT propiedad .
  • Mediante el uso del valor InfiniteMatchTimeout, si no se ha establecido ningún valor de tiempo de espera para toda la aplicación.

Importante

Se recomienda establecer un valor de tiempo de espera en todas las operaciones de coincidencia de patrones de expresión regular. Para obtener más información, consulte Procedimientos recomendados para expresiones regulares.

Ejemplos

En el ejemplo siguiente se usa una expresión regular para comprobar si hay repeticiones de palabras en una cadena. La expresión \b(?<word>\w+)\s+(\k<word>)\b regular se puede interpretar como se muestra en la tabla siguiente.

Patrón Descripción
\b Inicie la coincidencia en un límite de palabras.
(?<word>\w+) Coincide con uno o varios caracteres de palabra hasta un límite de palabras. Asigne a este grupo wordcapturado el nombre .
\s+ Coincide con uno o varios caracteres de espacio en blanco.
(\k<word>) Coincide con el grupo capturado denominado word.
\b Coincide con un límite de palabras.
using System;
using System.Text.RegularExpressions;

public class Test
{
    public static void Main ()
    {
        // Define a regular expression for repeated words.
        Regex rx = new Regex(@"\b(?<word>\w+)\s+(\k<word>)\b",
          RegexOptions.Compiled | RegexOptions.IgnoreCase);

        // Define a test string.
        string text = "The the quick brown fox  fox jumps over the lazy dog dog.";

        // Find matches.
        MatchCollection matches = rx.Matches(text);

        // Report the number of matches found.
        Console.WriteLine("{0} matches found in:\n   {1}",
                          matches.Count,
                          text);

        // Report on each match.
        foreach (Match match in matches)
        {
            GroupCollection groups = match.Groups;
            Console.WriteLine("'{0}' repeated at positions {1} and {2}",
                              groups["word"].Value,
                              groups[0].Index,
                              groups[1].Index);
        }
    }
}

// The example produces the following output to the console:
//       3 matches found in:
//          The the quick brown fox  fox jumps over the lazy dog dog.
//       'The' repeated at positions 0 and 4
//       'fox' repeated at positions 20 and 25
//       'dog' repeated at positions 49 and 53
Imports System.Text.RegularExpressions

Public Module Test

    Public Sub Main()
        ' Define a regular expression for repeated words.
        Dim rx As New Regex("\b(?<word>\w+)\s+(\k<word>)\b", _
               RegexOptions.Compiled Or RegexOptions.IgnoreCase)

        ' Define a test string.        
        Dim text As String = "The the quick brown fox  fox jumps over the lazy dog dog."
        
        ' Find matches.
        Dim matches As MatchCollection = rx.Matches(text)

        ' Report the number of matches found.
        Console.WriteLine("{0} matches found in:", matches.Count)
        Console.WriteLine("   {0}", text)

        ' Report on each match.
        For Each match As Match In matches
            Dim groups As GroupCollection = match.Groups
            Console.WriteLine("'{0}' repeated at positions {1} and {2}", _ 
                              groups.Item("word").Value, _
                              groups.Item(0).Index, _
                              groups.Item(1).Index)
        Next
    End Sub
End Module
' The example produces the following output to the console:
'       3 matches found in:
'          The the quick brown fox  fox jumps over the lazy dog dog.
'       'The' repeated at positions 0 and 4
'       'fox' repeated at positions 20 and 25
'       'dog' repeated at positions 49 and 53

En el ejemplo siguiente se muestra el uso de una expresión regular para comprobar si una cadena representa un valor de moneda o tiene el formato correcto para representar un valor de moneda. En este caso, la expresión regular se compila dinámicamente a partir de las NumberFormatInfo.CurrencyDecimalSeparatorpropiedades , CurrencyDecimalDigitsNumberFormatInfo.CurrencySymbol, , NumberFormatInfo.NegativeSigny NumberFormatInfo.PositiveSign para la referencia cultural en-US. La expresión regular resultante es ^\s*[\+-]?\s?\$?\s?(\d*\.?\d{2}?){1}$. Esta expresión regular se puede interpretar como se muestra en la tabla siguiente.

Patrón Descripción
^ Comience al principio de la cadena.
\s* Busca coincidencias con cero o más caracteres de espacio en blanco.
[\+-]? Coincide con cero o una aparición del signo positivo o del signo negativo.
\s? Busca coincidencias con cero o un carácter de espacio en blanco.
\$? Coincide con cero o una aparición del signo de dólar.
\s? Busca coincidencias con cero o un carácter de espacio en blanco.
\d* Busca cero o más dígitos decimales.
\.? Coincide con cero o un símbolo de separador decimal.
(\d{2})? Grupo de captura 1: coincide con dos dígitos decimales cero o una vez.
(\d*\.?(\d{2})?){1} Coincide con el patrón de dígitos enteros y fraccionarios separados por un símbolo decimal al menos una vez.
$ Coincide con el final de la cadena.

En este caso, la expresión regular supone que una cadena de moneda válida no contiene símbolos separadores de grupo y que no tiene dígitos fraccionarios ni el número de dígitos fraccionarios definidos por la propiedad de CurrencyDecimalDigits la referencia cultural especificada.

using System;
using System.Globalization;
using System.Text.RegularExpressions;

public class Example
{
    public static void Main()
    {
        // Get the en-US NumberFormatInfo object to build the regular 
        // expression pattern dynamically.
        NumberFormatInfo nfi = CultureInfo.GetCultureInfo("en-US").NumberFormat;

        // Define the regular expression pattern.
        string pattern;
        pattern = @"^\s*[";
        // Get the positive and negative sign symbols.
        pattern += Regex.Escape(nfi.PositiveSign + nfi.NegativeSign) + @"]?\s?";
        // Get the currency symbol.
        pattern += Regex.Escape(nfi.CurrencySymbol) + @"?\s?";
        // Add integral digits to the pattern.
        pattern += @"(\d*";
        // Add the decimal separator.
        pattern += Regex.Escape(nfi.CurrencyDecimalSeparator) + "?";
        // Add the fractional digits.
        pattern += @"(\d{";
        // Determine the number of fractional digits in currency values.
        pattern += nfi.CurrencyDecimalDigits.ToString() + "})?){1}$";

        Console.WriteLine($"Pattern is {pattern}\n");

        Regex rgx = new Regex(pattern);

        // Define some test strings.
        string[] tests = { "-42", "19.99", "0.001", "100 USD",
                         ".34", "0.34", "1,052.21", "$10.62",
                         "+1.43", "-$0.23" };

        // Check each test string against the regular expression.
        foreach (string test in tests)
        {
            if (rgx.IsMatch(test))
                Console.WriteLine($"{test} is a currency value.");
            else
                Console.WriteLine($"{test} is not a currency value.");
        }
    }
}
// The example displays the following output:
//       Pattern is ^\s*[\+-]?\s?\$?\s?(\d*\.?(\d{2})?){1}$
//
//       -42 is a currency value.
//       19.99 is a currency value.
//       0.001 is not a currency value.
//       100 USD is not a currency value.
//       .34 is a currency value.
//       0.34 is a currency value.
//       1,052.21 is not a currency value.
//       $10.62 is a currency value.
//       +1.43 is a currency value.
//       -$0.23 is a currency value.
Imports System.Globalization
Imports System.Text.RegularExpressions

Public Module Example
   Public Sub Main()
      ' Get the current NumberFormatInfo object to build the regular 
      ' expression pattern dynamically.
      Dim nfi As NumberFormatInfo = CultureInfo.GetCultureInfo("en-US").NumberFormat

      ' Define the regular expression pattern.
      Dim pattern As String 
      pattern = "^\s*["
      ' Get the positive and negative sign symbols.
      pattern += Regex.Escape(nfi.PositiveSign + nfi.NegativeSign) + "]?\s?"
      ' Get the currency symbol.
      pattern += Regex.Escape(nfi.CurrencySymbol) + "?\s?"
      ' Add integral digits to the pattern.
      pattern += "(\d*"
      ' Add the decimal separator.
      pattern += Regex.Escape(nfi.CurrencyDecimalSeparator) + "?"
      ' Add the fractional digits.
      pattern += "(\d{"
      ' Determine the number of fractional digits in currency values.
      pattern += nfi.CurrencyDecimalDigits.ToString() + "})?){1}$"
      
      Console.WriteLine("Pattern is {0}", pattern)
      Console.WriteLine()
      
      Dim rgx As New Regex(pattern)

      ' Define some test strings.
      Dim tests() As String = {"-42", "19.99", "0.001", "100 USD", _
                               ".34", "0.34", "1,052.21", "$10.62", _
                               "+1.43", "-$0.23" }

      ' Check each test string against the regular expression.
      For Each test As String In tests
         If rgx.IsMatch(test) Then
            Console.WriteLine("{0} is a currency value.", test)
         Else
            Console.WriteLine("{0} is not a currency value.", test)
         End If
      Next
   End Sub
End Module
' The example displays the following output:
'       Pattern is ^\s*[\+-]?\s?\$?\s?(\d*\.?(\d{2})?){1}$
'
'       -42 is a currency value.
'       19.99 is a currency value.
'       0.001 is not a currency value.
'       100 USD is not a currency value.
'       .34 is a currency value.
'       0.34 is a currency value.
'       1,052.21 is not a currency value.
'       $10.62 is a currency value.
'       +1.43 is a currency value.
'       -$0.23 is a currency value.

Dado que la expresión regular de este ejemplo se compila dinámicamente, no sabe en tiempo de diseño si el símbolo de moneda, el signo decimal o los signos positivos y negativos de la referencia cultural especificada (en-US en este ejemplo) podrían ser malinterpretados por el motor de expresiones regulares como operadores del lenguaje de expresiones regulares. Para evitar cualquier interpretación incorrecta, el ejemplo pasa cada cadena generada dinámicamente al Escape método .