Condividi tramite


Espressioni regolari di .NET

Le espressioni regolari offrono un metodo potente, flessibile ed efficiente per l'elaborazione del testo. L'ampia notazione di pattern matching delle espressioni regolari consente di analizzare rapidamente grandi quantità di testo.

  • Trovare modelli di caratteri specifici.
  • Convalidare il testo per assicurarsi che corrisponda a un criterio predefinito, ad esempio un indirizzo di posta elettronica.
  • Estrarre, modificare, sostituire o eliminare sottostringhe di testo.
  • Aggiungere stringhe estratte a una raccolta per generare un report.

Per molte applicazioni che gestiscono stringhe o che analizzano grandi blocchi di testo, le espressioni regolari sono uno strumento indispensabile.

Funzionamento delle espressioni regolari

Il centro dell'elaborazione del testo con espressioni regolari è il motore delle espressioni regolari, rappresentato dall'oggetto System.Text.RegularExpressions.Regex in .NET. L'elaborazione minima del testo tramite espressioni regolari richiede che il motore delle espressioni regolari venga fornito con i due elementi di informazioni seguenti:

  • Modello di espressione regolare da identificare nel testo.

    In .NET, i modelli di espressione regolare sono definiti da una sintassi o un linguaggio speciale, compatibile con le espressioni regolari Perl 5 e aggiunge alcune funzionalità, ad esempio la corrispondenza da destra a sinistra. Per altre informazioni, vedere Linguaggio delle espressioni regolari - Guida di riferimento rapido.

  • Testo da analizzare per il pattern di espressione regolare.

I metodi della Regex classe consentono di eseguire le operazioni seguenti:

Per una panoramica del modello a oggetti delle espressioni regolari, vedere Modello a oggetti di espressione regolare.

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

Esempi di espressioni regolari

La String classe include metodi di ricerca e sostituzione di stringhe che è possibile usare quando si desidera individuare stringhe letterali in una stringa più grande. Le espressioni regolari sono più utili quando si vuole individuare una delle diverse sottostringhe in una stringa più grande o quando si vogliono identificare i criteri in una stringa, come illustrato negli esempi seguenti.

Avvertimento

Quando si usa System.Text.RegularExpressions per elaborare un input non attendibile, specificare un timeout. Un utente malintenzionato può fornire input a RegularExpressions, causando un attacco di negazione del servizio . Le API del framework di ASP.NET Core che utilizzano RegularExpressions trasmettono un timeout.

Suggerimento

Lo spazio dei nomi System.Web.RegularExpressions contiene numerosi oggetti di espressioni regolari che implementano modelli predefiniti di espressioni regolari per l'analisi di stringhe da documenti HTML, XML e ASP.NET. Ad esempio, la TagRegex classe identifica i tag di inizio in una stringa e la CommentRegex classe identifica ASP.NET commenti in una stringa.

Esempio 1: Sostituire le sottostringhe

Si supponga che una lista di distribuzione contenga nomi che talvolta includono un titolo (Mr., Mrs., Miss o Ms.) insieme a un nome e un cognome. Si supponga di non voler includere i titoli quando si generano etichette per buste dall'elenco. In tal caso, è possibile usare un'espressione regolare per rimuovere i titoli, come illustrato nell'esempio seguente:

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
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "(Mr\.? |Mrs\.? |Miss |Ms\.? )"
        Dim names() As String = {"Mr. Henry Hunt", "Ms. Sara Samuels", _
                                  "Abraham Adams", "Ms. Nicole Norris"}
        For Each name As String In names
            Console.WriteLine(Regex.Replace(name, pattern, String.Empty))
        Next
    End Sub
End Module
' The example displays the following output:
'    Henry Hunt
'    Sara Samuels
'    Abraham Adams
'    Nicole Norris

Il modello (Mr\.? |Mrs\.? |Miss |Ms\.? ) di una espressione regolare corrisponde a qualsiasi occorrenza di "Mr ", "Mr. ", "Mrs ", "Mrs. ", "Miss ", "Ms " o "Ms. ". La chiamata al Regex.Replace metodo sostituisce la stringa corrispondente con String.Empty; in altre parole, la rimuove dalla stringa originale.

Esempio 2: Identificare le parole duplicate

La duplicazione accidentale delle parole è un errore comune che gli autori fanno. Usare un'espressione regolare per identificare le parole duplicate, come illustrato nell'esempio seguente:

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($"{match.Value} (duplicates '{match.Groups[1].Value}') at position {match.Index}");
   }
}
// The example displays the following output:
//       This this (duplicates 'This') at position 0
//       a a (duplicates 'a') at position 66
Imports System.Text.RegularExpressions

Module modMain
    Public Sub Main()
        Dim pattern As String = "\b(\w+?)\s\1\b"
        Dim input As String = "This this is a nice day. What about this? This tastes good. I saw a a dog."
        For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
            Console.WriteLine("{0} (duplicates '{1}') at position {2}", _
                              match.Value, match.Groups(1).Value, match.Index)
        Next
    End Sub
End Module
' The example displays the following output:
'       This this (duplicates 'This') at position 0
'       a a (duplicates 'a') at position 66

Il criterio \b(\w+?)\s\1\b di espressione regolare può essere interpretato come segue:

Modello Interpretazione
\b Inizia dal confine di una parola.
(\w+?) Corrispondere a uno o più caratteri di parola, ma col minor numero possibile. Insieme, formano un gruppo a cui è possibile fare riferimento come \1.
\s Trova la corrispondenza con un carattere di spazio bianco.
\1 Confronta la sottostringa corrispondente al gruppo denominato \1.
\b Identifica un confine di parola.

Il Regex.Matches metodo viene chiamato con opzioni di espressione regolare impostate su RegexOptions.IgnoreCase. Pertanto, l'operazione di corrispondenza non fa distinzione tra maiuscole e minuscole, e l'esempio identifica la sottostringa "This this" come un duplicato.

La stringa di input include la sottostringa "this"? Questo". Tuttavia, a causa del segno di punteggiatura intermedio, non viene identificato come duplicazione.

Esempio 3: Creare dinamicamente un'espressione regolare sensibile alla cultura

Nell'esempio seguente viene illustrata la potenza delle espressioni regolari combinate con la flessibilità offerta dalle funzionalità di globalizzazione di .NET. Usa l'oggetto NumberFormatInfo per determinare il formato dei valori di valuta nella cultura corrente del sistema. Usa quindi tali informazioni per costruire in modo dinamico un'espressione regolare che estrae i valori di valuta dal testo. Per ogni corrispondenza, estrae il sottogruppo che contiene solo la stringa numerica, la converte in un valore Decimal e calcola un totale progressivo.

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 {matches.Count} matches.");

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

      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 {expenses[expenses.Count - 1]:C2}.");
      else
         Console.WriteLine($"The expenses total {total:C2}.");
   }
}
// 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.
Imports System.Collections.Generic
Imports System.Globalization
Imports System.Text.RegularExpressions

Public Module Example
    Public Sub Main()
        ' Define text to be parsed.
        Dim input As String = "Office expenses on 2/13/2008:" + vbCrLf + _
                              "Paper (500 sheets)                      $3.95" + vbCrLf + _
                              "Pencils (box of 10)                     $1.00" + vbCrLf + _
                              "Pens (box of 10)                        $4.49" + vbCrLf + _
                              "Erasers                                 $2.19" + vbCrLf + _
                              "Ink jet printer                        $69.95" + vbCrLf + vbCrLf + _
                              "Total Expenses                        $ 81.58" + vbCrLf
        ' Get current culture's NumberFormatInfo object.
        Dim nfi As NumberFormatInfo = CultureInfo.CurrentCulture.NumberFormat
        ' Assign needed property values to variables.
        Dim currencySymbol As String = nfi.CurrencySymbol
        Dim symbolPrecedesIfPositive As Boolean = CBool(nfi.CurrencyPositivePattern Mod 2 = 0)
        Dim groupSeparator As String = nfi.CurrencyGroupSeparator
        Dim decimalSeparator As String = nfi.CurrencyDecimalSeparator

        ' Form regular expression pattern.
        Dim pattern As String = Regex.Escape(CStr(IIf(symbolPrecedesIfPositive, currencySymbol, ""))) + _
                                "\s*[-+]?" + "([0-9]{0,3}(" + groupSeparator + "[0-9]{3})*(" + _
                                Regex.Escape(decimalSeparator) + "[0-9]+)?)" + _
                                CStr(IIf(Not symbolPrecedesIfPositive, currencySymbol, ""))
        Console.WriteLine("The regular expression pattern is: ")
        Console.WriteLine("   " + pattern)

        ' Get text that matches regular expression pattern.
        Dim matches As MatchCollection = 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.
        Dim expenses As New List(Of Decimal)

        For Each match As Match In matches
            expenses.Add(Decimal.Parse(match.Groups.Item(1).Value))
        Next

        ' Determine whether total is present and if present, whether it is correct.
        Dim total As Decimal
        For Each value As Decimal In expenses
            total += value
        Next

        If total / 2 = expenses(expenses.Count - 1) Then
            Console.WriteLine("The expenses total {0:C2}.", expenses(expenses.Count - 1))
        Else
            Console.WriteLine("The expenses total {0:C2}.", total)
        End If
    End Sub
End Module
' 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.

Su un computer con impostazioni culturali correnti in Inglese - Stati Uniti (en-US), l'esempio compila dinamicamente l'espressione regolare \$\s*[-+]?([0-9]{0,3}(,[0-9]{3})*(\.[0-9]+)?). Questo criterio di espressione regolare può essere interpretato come segue:

Modello Interpretazione
\$ Cercare una singola occorrenza del simbolo di dollaro ($) nella stringa di input. La stringa del modello di espressione regolare include un backslash per indicare che il simbolo del dollaro deve essere interpretato letteralmente anziché come ancoraggio delle espressioni regolari. Il simbolo $ da solo indicherebbe che il motore delle espressioni regolari dovrebbe provare a iniziare la corrispondenza alla fine di una stringa. Per assicurarsi che il simbolo di valuta della cultura corrente non venga interpretato erroneamente come un simbolo di espressione regolare, nell'esempio viene chiamato il metodo Regex.Escape per eseguire l'escape su quel carattere.
\s* Cerca zero o più occorrenze di un carattere di spazio.
[-+]? Cerca zero o un'occorrenza di un segno matematico positivo o negativo.
([0-9]{0,3}(,[0-9]{3})*(\.[0-9]+)?) Le parentesi esterne definiscono questa espressione come gruppo di acquisizione o sottoespressione. Se viene trovata una corrispondenza, è possibile recuperare informazioni su questa parte della stringa corrispondente dal secondo Group oggetto nell'oggetto GroupCollection restituito dalla Match.Groups proprietà . Il primo elemento della raccolta rappresenta l'intera corrispondenza.
[0-9]{0,3} Cercare da zero a tre occorrenze delle cifre decimali da 0 a 9.
(,[0-9]{3})* Cerca zero o più occorrenze di un separatore di gruppo seguito da tre cifre decimali.
\. Cercare una singola occorrenza del separatore decimale.
[0-9]+ Cerca una o più cifre decimali.
(\.[0-9]+)? Cercare zero o una sola occorrenza del separatore decimale, seguito da almeno una cifra decimale.

Se ogni sottopattern viene trovato nella stringa di input, la corrispondenza ha esito positivo e un Match oggetto che contiene informazioni sulla corrispondenza viene aggiunto all'oggetto MatchCollection .

Titolo Descrizione
Linguaggio di espressioni regolari - Riferimento rapido Fornisce informazioni sul set di caratteri, operatori e costrutti che è possibile usare per definire espressioni regolari.
Modello a oggetti delle espressioni regolari Fornisce informazioni ed esempi di codice che illustrano come usare le classi di espressioni regolari.
Dettagli del comportamento delle espressioni regolari Fornisce informazioni sulle funzionalità e sul comportamento delle espressioni regolari .NET.
Usare espressioni regolari in Visual Studio

Riferimento