Espressioni regolari di .NET Framework

Le espressioni regolari ("regular expression") garantiscono un metodo efficace e flessibile per l'elaborazione di testo. L'ampia notazione per la formulazione dei criteri di ricerca fornita dalle espressioni regolari consente di analizzare rapidamente grandi quantità di testo per trovare combinazioni di caratteri specifiche, per convalidare il testo verificandone la corrispondenza con un modello predefinito, ad esempio un indirizzo di posta elettronica, per estrarre, modificare, sostituire o eliminare sottostringhe di testo e per aggiungere le stringhe estratte a un insieme per generare un rapporto. Per numerose applicazioni che gestiscono stringhe o che analizzano grandi blocchi di testo, le espressioni regolari rappresentano uno strumento indispensabile.

Funzionamento delle espressioni regolari

Il motore di elaborazione di testo tramite espressioni regolari è rappresentato dall'oggetto System.Text.RegularExpressions.Regex in .NET Framework. L'elaborazione di testo tramite espressioni regolari richiede che al motore delle espressioni regolari vengano fornite almeno le due informazioni seguenti:

  • Modello di espressione regolare da identificare nel testo.

    In .NET Framework i modelli di espressione regolare vengono definiti tramite un linguaggio o una sintassi speciale, compatibile con le espressioni regolari Perl 5, che offre funzionalità aggiuntive come la corrispondenza da destra verso sinistra. Per ulteriori informazioni, vedere Elementi del linguaggio di espressioni regolari.

  • Testo da analizzare per il modello di espressione regolare.

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

Per cenni preliminari sul modello a oggetti delle espressioni regolari, vedere Modello a oggetti delle espressioni regolari.

Esempi di espressioni regolari

La classe String include numerosi metodi di ricerca e sostituzione di stringhe che è possibile utilizzare quando si desidera individuare stringhe letterali in una stringa più grande. Le espressioni regolari sono utili per lo più quando si desidera individuare una di diverse sottostringhe in una stringa più grande o quando si desidera identificare modelli in una stringa, come illustrato negli esempi seguenti.

Esempio 1: sostituzione di sottostringhe

Si presupponga che una lista di distribuzione contenga nomi che talvolta includono un titolo (Mr., Mrs., Miss, or Ms.) oltre al nome e al cognome. Se non si desidera includere i titoli quando si generano etichette per le buste dall'elenco, è possibile utilizzare un'espressione regolare per rimuovere i titoli, come illustrato nell'esempio seguente.

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

Il modello di espressione regolare (Mr\.? |Mrs\.? |Miss |Ms\.? ) trova una corrispondenza di tutte le occorrenza di "Mr ", "Mr. " , "Mrs ", "Mrs. " , "Miss ", "Ms o "Ms. " . La chiamata al metodo Regex.Replace sostituisce la stringa corrispondente con String.Empty, ovvero la rimuove dalla stringa originale.

Esempio 2: identificazione di parole duplicate

La duplicazione accidentale delle parole è un errore comune commesso da chi scrive. È possibile utilizzare un'espressione regolare per identificare le parole duplicate, come illustrato nell'esempio seguente.

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

Il modello di espressione regolare \b(\w+?)\s\1\b può essere interpretato nel modo seguente:

\b

Iniziare dal confine di una parola.

(\w+)

Trovare la corrispondenza di uno o più caratteri alfanumerici. I caratteri insieme formano un gruppo a cui è possibile fare riferimento come \1.

\s

Trovare la corrispondenza di uno spazio vuoto.

\1

Trovare la corrispondenza della sottostringa equivalente al gruppo denominato \1.

\b

Trovare la corrispondenza di un confine di parola.

Il metodo Regex.Matches viene chiamato con le opzioni relative alle espressioni regolari impostate su RegexOptions.IgnoreCase. Per l'operazione di corrispondenza non viene pertanto fatta distinzione tra maiuscole e minuscole e nell'esempio la sottostringa "This this" viene identificata come duplicato.

Si noti che la stringa di input include la sottostringa "this. This". Poiché tuttavia tra le due parole è presente un segno di punteggiatura, le parole non vengono identificate come duplicati.

Esempio 3: compilazione dinamica di un'espressione regolare dipendente dalle impostazioni cultura

Nell'esempio seguente vengono illustrate le potenzialità delle espressioni regolari combinate alla flessibilità offerta dalle funzionalità di globalizzazione di .NET Framework. Viene utilizzato l'oggetto NumberFormatInfo per determinare il formato dei valori di valuta nelle impostazioni cultura correnti del sistema. Queste informazioni vengono quindi utilizzate per costruire in modo dinamico un'espressione regolare per estrarre i valori di valuta dal testo. Per ogni corrispondenza, viene estratto il sottogruppo che contiene solo la stringa numerica, viene convertito in un valore Decimal e viene calcolato un totale parziale.

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.
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<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 {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.

In un computer le cui impostazioni cultura correnti sono Inglese - Stati Uniti (en-US), l'espressione regolare \$\s*[-+]?([0-9]{0,3}(,[0-9]{3})*(\.[0-9]+)?) viene compilata dinamicamente. Questo modello di espressione regolare può essere interpretato nel modo seguente:

\$

Cercare una singola occorrenza del simbolo di dollaro ($) nella stringa di input. La stringa del modello di espressione regolare include una barra rovesciata per indicare che il simbolo di dollaro deve essere interpretato letteralmente e non come un ancoraggio dell'espressione regolare. Il simbolo di $ da solo indica che il motore delle espressioni regolari deve tentare di iniziare la ricerca della corrispondenza alla fine di una stringa. Per garantire che il simbolo di valuta delle impostazioni cultura correnti non venga interpretato erroneamente come simbolo dell'espressione regolare, nell'esempio viene chiamato il metodo Escape per utilizzare caratteri di escape per il carattere.

\s*

Cercare zero o più occorrenze di uno spazio vuoto.

[-+]?

Cercare zero o una occorrenza di un segno positivo o negativo.

([0-9]{0,3}(,[0-9]{3})*(\.[0-9]+)?)

Le parentesi esterne che delimitano questa espressione la definiscono come gruppo Capture o come sottoespressione. Se viene trovata una corrispondenza, è possibile recuperare informazioni relative a questa parte della stringa corrispondente dal secondo oggetto Group nell'oggetto GroupCollection restituito dalla proprietà Match.Groups. Il primo dell'elemento dell'insieme rappresenta la corrispondenza completa.

[0-9]{0,3}

Cercare da zero a tre occorrenze delle cifre decimali comprese tra 0 e 9.

(,[0-9]{3})*

Cercare zero o più occorrenze di un separatore di gruppi seguito da tre cifre decimali.

\.

Cercare una singola occorrenza del separatore decimale.

[0-9]+

Cercare una o più cifre decimali.

(\.[0-9]+)?

Cercare zero o una occorrenza del separatore decimale seguito da almeno una cifra decimale.

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

Argomenti correlati

Titolo

Descrizione

Elementi del linguaggio di espressioni regolari

Vengono fornite informazioni sul set di caratteri, di operatori e di costrutti utilizzabili per definire le espressioni regolari.

Procedure consigliate per le espressioni regolari in .NET Framework

Vengono fornite indicazioni per ottimizzare le prestazioni delle espressioni regolari e per creare modelli di espressione regolare potenti e affidabili.

Modello a oggetti delle espressioni regolari

Vengono forniti esempi di codice ed informazioni che illustrano l'utilizzo delle classi di espressioni regolari.

Dettagli sul funzionamento delle espressioni regolari

Vengono fornite informazioni sulle funzionalità e il funzionamento delle espressioni regolari di .NET Framework.

Esempi di espressioni regolari

Vengono forniti esempi di codice che illustrano gli utilizzi tipici delle espressioni regolari.

Riferimenti

System.Text.RegularExpressions

System.Text.RegularExpressions.Regex