Condividi tramite


Classe System.Text.RegularExpressions.Regex

Questo articolo fornisce osservazioni supplementari alla documentazione di riferimento per questa API.

La Regex classe rappresenta . Motore delle espressioni regolari di NET. È possibile usare questa classe per:

  • Analizzare rapidamente grandi quantità di testo per trovare modelli di caratteri specifici.
  • Estrarre, modificare, sostituire o eliminare sottostringhe di testo.
  • Aggiungere le stringhe estratte a una raccolta per generare un report.

Nota

Se si desidera convalidare una stringa determinando se è conforme a un modello di espressione regolare specifico, è possibile usare la System.Configuration.RegexStringValidator classe .

Per usare le espressioni regolari, definire il modello da identificare in un flusso di testo usando la sintassi documentata in Linguaggio di espressioni regolari - Riferimento rapido. Successivamente, è possibile creare un'istanza di un Regex oggetto facoltativamente. Infine, si chiama un metodo che esegue un'operazione, ad esempio la sostituzione di testo corrispondente al criterio di espressione regolare o l'identificazione di una corrispondenza del criterio.

Per altre informazioni sul linguaggio delle espressioni regolari, vedere Linguaggio delle espressioni regolari - Riferimento rapido o scaricare e stampare una di queste brochure:

Riferimento rapido in formatoWord (.docx) Riferimento rapido in formato PDF (.pdf)

Metodi regex e string

La System.String classe include diversi metodi di ricerca e confronto che è possibile usare per eseguire criteri di ricerca con testo. Ad esempio, i metodi , String.EndsWithe determinano se un'istanza String.Containsdi stringa contiene una sottostringa specificata e i String.IndexOfmetodi , String.LastIndexOfString.IndexOfAny, e String.LastIndexOfAny restituiscono la posizione iniziale di una sottostringa specificata in una String.StartsWith stringa. Usare i metodi della System.String classe quando si cerca una stringa specifica. Usare la Regex classe quando si cerca un criterio specifico in una stringa. Per altre informazioni ed esempi, vedere Espressioni regolari .NET.

Metodi statici e di istanza

Dopo aver definito un criterio di espressione regolare, è possibile fornirlo al motore delle espressioni regolari in uno dei due modi seguenti:

  • Creando un'istanza di un Regex oggetto che rappresenta l'espressione regolare. A tale scopo, passare il criterio di espressione regolare a un Regex costruttore. Un Regex oggetto non è modificabile. Quando si crea un'istanza di un oggetto con un'espressione Regex regolare, non è possibile modificare l'espressione regolare dell'oggetto.

  • Specificando sia l'espressione regolare che il testo da cercare in un static metodo (Shared in Visual Basic). Regex In questo modo è possibile usare un'espressione regolare senza creare in modo esplicito un Regex oggetto .

Tutti i Regex metodi di identificazione dei criteri includono overload statici e dell'istanza.

Il motore delle espressioni regolari deve compilare un modello specifico prima di poter usare il modello. Poiché Regex gli oggetti non sono modificabili, si tratta di una routine monouso che si verifica quando viene chiamato un Regex costruttore di classe o un metodo statico. Per eliminare la necessità di compilare ripetutamente una singola espressione regolare, il motore delle espressioni regolari memorizza nella cache le espressioni regolari compilate usate nelle chiamate al metodo statico. Di conseguenza, i metodi di criteri di ricerca delle espressioni regolari offrono prestazioni confrontabili per i metodi statici e di istanza. Tuttavia, la memorizzazione nella cache può influire negativamente sulle prestazioni nei due casi seguenti:

  • Quando si usano chiamate al metodo statico con un numero elevato di espressioni regolari. Per impostazione predefinita, il motore delle espressioni regolari memorizza nella cache le 15 espressioni regolari statiche usate più di recente. Se l'applicazione usa più di 15 espressioni regolari statiche, è necessario ricompilare alcune espressioni regolari. Per evitare questa ricompilazione, è possibile aumentare la Regex.CacheSize proprietà .

  • Quando si crea un'istanza di nuovi Regex oggetti con espressioni regolari compilate in precedenza. Ad esempio, il codice seguente definisce un'espressione regolare per individuare parole duplicate in un flusso di testo. Anche se l'esempio usa una singola espressione regolare, crea un'istanza di un nuovo Regex oggetto per elaborare ogni riga di testo. Ciò comporta la ricompilazione dell'espressione regolare con ogni iterazione del ciclo.

    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()
    

    Per evitare la ricompilazione, è necessario creare un'istanza di un singolo Regex oggetto accessibile a tutto il codice che lo richiede, come illustrato nell'esempio riscritto seguente.

    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()
    

Eseguire operazioni di espressione regolare

Indipendentemente dal fatto che si decida di creare un'istanza di un Regex oggetto e chiamare i relativi metodi o chiamare metodi statici, la Regex classe offre la funzionalità di corrispondenza dei criteri seguente:

  • Convalida di una corrispondenza. Chiamare il IsMatch metodo per determinare se è presente una corrispondenza.

  • Recupero di una singola corrispondenza. Chiamare il Match metodo per recuperare un Match oggetto che rappresenta la prima corrispondenza in una stringa o in parte di una stringa. È possibile recuperare le corrispondenze successive chiamando il Match.NextMatch metodo .

  • Recupero di tutte le corrispondenze. Chiamare il Matches metodo per recuperare un System.Text.RegularExpressions.MatchCollection oggetto che rappresenta tutte le corrispondenze trovate in una stringa o in una parte di una stringa.

  • Sostituzione del testo corrispondente. Chiamare il metodo per sostituire il Replace testo corrispondente. Il testo sostitutivo può essere definito anche da un'espressione regolare. Inoltre, alcuni dei metodi includono un MatchEvaluator parametro che consente di definire a livello di Replace codice il testo sostitutivo.

  • Creazione di una matrice di stringhe formata da parti di una stringa di input. Chiamare il Split metodo per dividere una stringa di input in corrispondenza delle posizioni definite dall'espressione regolare.

Oltre ai metodi di ricerca, la Regex classe include diversi metodi speciali:

  • Il Escape metodo esegue l'escape di tutti i caratteri che possono essere interpretati come operatori di espressioni regolari in un'espressione regolare o in una stringa di input.
  • Il Unescape metodo rimuove questi caratteri di escape.
  • Il CompileToAssembly metodo crea un assembly che contiene espressioni regolari predefinite. .NET contiene esempi di questi assembly speciali nello spazio dei System.Web.RegularExpressions nomi .

Definire un valore di timeout

.NET supporta un linguaggio di espressioni regolari completo che offre una notevole potenza e flessibilità nei criteri di ricerca. Tuttavia, la potenza e la flessibilità comportano un costo: il rischio di prestazioni scarse. Le espressioni regolari con prestazioni scarse sono sorprendentemente facili da creare. In alcuni casi, le operazioni di espressione regolare che si basano su un backtracking eccessivo possono sembrare smettere di rispondere quando elaborano il testo che corrisponde quasi al criterio di espressione regolare. Per altre informazioni sul motore delle espressioni regolari .NET, vedere Dettagli del comportamento delle espressioni regolari. Per altre informazioni sull'eccessivo backtracking, vedere Backtracking.

A partire da .NET Framework 4.5, è possibile definire un intervallo di timeout per le corrispondenze di espressioni regolari per limitare il backtracking eccessivo. A seconda del criterio di espressione regolare e del testo di input, il tempo di esecuzione può superare l'intervallo di timeout specificato, ma non impiega più tempo per il backtracking rispetto all'intervallo di timeout specificato. Se il motore delle espressioni regolari raggiunge il timeout, genera un'eccezione RegexMatchTimeoutException . Nella maggior parte dei casi, ciò impedisce al motore delle espressioni regolari di sprecare potenza di elaborazione cercando di trovare una corrispondenza con il testo che corrisponde quasi al criterio di espressione regolare. Potrebbe anche indicare, tuttavia, che l'intervallo di timeout è stato impostato troppo basso o che il carico corrente del computer ha causato una riduzione complessiva delle prestazioni.

La modalità di gestione dell'eccezione dipende dalla causa dell'eccezione. Se l'eccezione si verifica perché l'intervallo di timeout è impostato troppo basso o a causa di un carico eccessivo del computer, è possibile aumentare l'intervallo di timeout e ripetere l'operazione di corrispondenza. Se l'eccezione si verifica perché l'espressione regolare si basa su un backtracking eccessivo, è possibile presupporre che una corrispondenza non esista e, facoltativamente, è possibile registrare informazioni che consentiranno di modificare il criterio di espressione regolare.

È possibile impostare un intervallo di timeout chiamando il costruttore quando si crea un'istanza Regex(String, RegexOptions, TimeSpan) di un oggetto espressione regolare. Per i metodi statici, è possibile impostare un intervallo di timeout chiamando un overload di un metodo corrispondente con un matchTimeout parametro . Se non si imposta un valore di timeout in modo esplicito, il valore di timeout predefinito viene determinato nel modo seguente:

  • Usando il valore di timeout a livello di applicazione, se presente. Impostare il valore di timeout a livello di applicazione chiamando il AppDomain.SetData metodo per assegnare la rappresentazione di stringa di un TimeSpan valore alla REGEX_DEFAULT_MATCH_TIMEOUT proprietà .
  • Usando il valore InfiniteMatchTimeout, se non è stato impostato alcun valore di timeout a livello di applicazione.

Importante

È consigliabile impostare un valore di timeout in tutte le operazioni di criteri di ricerca di espressioni regolari. Per altre informazioni, vedere Procedure consigliate per le espressioni regolari.

Esempi

Nell'esempio seguente viene utilizzata un'espressione regolare per verificare la presenza di occorrenze ripetute di parole in una stringa. L'espressione \b(?<word>\w+)\s+(\k<word>)\b regolare può essere interpretata come illustrato nella tabella seguente.

Modello Descrizione
\b Avviare la corrispondenza in corrispondenza di un limite di parola.
(?<word>\w+) Trova la corrispondenza di uno o più caratteri di parola fino al limite di una parola. Assegnare al gruppo wordacquisito il nome .
\s+ Trova uno o più spazi vuoti.
(\k<word>) Trovare la corrispondenza con il gruppo acquisito denominato word.
\b Trova la corrispondenza di un confine di parola.
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

Nell'esempio seguente viene illustrato l'uso di un'espressione regolare per verificare se una stringa rappresenta un valore di valuta o ha il formato corretto per rappresentare un valore di valuta. In questo caso, l'espressione regolare viene compilata dinamicamente dalle NumberFormatInfo.CurrencyDecimalSeparatorproprietà , CurrencyDecimalDigitsNumberFormatInfo.CurrencySymbol, NumberFormatInfo.NegativeSign, e NumberFormatInfo.PositiveSign per le impostazioni cultura en-US. L'espressione regolare risultante è ^\s*[\+-]?\s?\$?\s?(\d*\.?\d{2}?){1}$. Questa espressione regolare può essere interpretata come illustrato nella tabella seguente.

Modello Descrizione
^ Iniziare all'inizio della stringa.
\s* Trovare la corrispondenza di zero o più spazi vuoti.
[\+-]? Trova la corrispondenza con zero o una occorrenza del segno positivo o del segno negativo.
\s? Trova la corrispondenza di uno o nessuno spazio vuoto.
\$? Trova la corrispondenza con zero o una occorrenza del segno di dollaro.
\s? Trova la corrispondenza di uno o nessuno spazio vuoto.
\d* Ricerca la corrispondenza di zero o di più cifre decimali.
\.? Trova la corrispondenza con zero o un simbolo di virgola decimale.
(\d{2})? Gruppo di acquisizione 1: corrisponde a due cifre decimali zero o una volta.
(\d*\.?(\d{2})?){1} Trova la corrispondenza con il modello di cifre integrali e frazionarie separate da un simbolo di virgola decimale esattamente una volta.
$ Trova la corrispondenza con la fine della stringa.

In questo caso, l'espressione regolare presuppone che una stringa di valuta valida non contenga simboli separatori di gruppo e che non contenga cifre frazionarie o il numero di cifre frazionarie definite dalla proprietà delle CurrencyDecimalDigits impostazioni cultura specificate.

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.

Poiché l'espressione regolare in questo esempio viene compilata in modo dinamico, non si sa in fase di progettazione se il simbolo di valuta, il segno decimale o il segno positivo e negativo delle impostazioni cultura specificate (en-US in questo esempio) potrebbe essere interpretato erroneamente dal motore delle espressioni regolari come operatori del linguaggio delle espressioni regolari. Per evitare eventuali errori di interpretazione, l'esempio passa ogni stringa generata dinamicamente al Escape metodo .