Condividi tramite


Quantificatori

I quantificatori specificano il numero di istanze di un carattere, un gruppo o una classe di caratteri che devono essere presenti nell'input affinché venga trovata una corrispondenza. Nella tabella seguente sono elencati i quantificatori supportati da .NET Framework.

Quantificatore greedy

Quantificatore lazy

Oggetto di descrizione

*

*?

Ottiene zero o più volte una corrispondenza.

+

+?

Ottiene una corrispondenza una o più volte.

?

??

Ottiene zero o una volta una corrispondenza.

{}n

{}?n

Ottiene una corrispondenza esatta n volte.

{,}n

{,}?n

Trova corrispondenze per almeno n volte.

{n,m}

{n,m}?

Ottiene una corrispondenza da n a m volte.

Le quantità n e m sono costanti integer. In genere, i quantificatori sono greedy: fanno in modo che il motore delle espressioni regolari individui corrispondenze per il maggior numero possibile di occorrenze di modelli specifici. L'aggiunta del carattere ? a un quantificatore lo rende lazy; fa in modo che il motore delle espressioni regolari trovi il minor numero possibile di corrispondenze. Per una descrizione della differenza tra quantificatore greedy e lazy, vedere la sezione Quantificatore greedy e lazy riportata più avanti in questo argomento.

Nota importanteImportante

Annidare i quantificatori (ad esempio, come nel modello di espressione regolare (a*)*) può aumentare il numero dei confronti che il motore delle espressioni regolari deve eseguire, come funzione esponenziale del numero di caratteri nella stringa di input.Per ulteriori informazioni su tale comportamento e relative soluzioni alternative, vedere Backtracking.

Quantificatori delle espressioni regolari

Nelle seguenti sezioni vengono elencati i quantificatori supportati dalle espressioni regolari di .NET Framework.

NotaNota

Se i caratteri *, +, ?, { e } sono presenti in un criterio di espressione regolare, il motore delle espressioni regolari li interpreta come quantificatori o parte di costrutti del quantificatore a meno che siano inclusi in una classe di caratteri.Per interpretare questi caratteri come caratteri letterali esterni a una classe di caratteri, è necessario utilizzare caratteri di escape preceduti da una barra rovesciata.Ad esempio, in un criterio di espressione regolare la stringa \* viene interpretata come un carattere letterale asterisco ("*").

Ottiene zero o più volte una corrispondenza: *

Il quantificatore * trova zero o più corrispondenze con l'elemento precedente. È equivalente al quantificatore {0,}. * è un quantificatore greedy il cui equivalente lazy è *?.

Questa espressione regolare viene illustrata nell'esempio seguente. Delle nove cifre della stringa di input, cinque corrispondono al modello e quattro (95, 929, 9129 e 9919) no.

Dim pattern As String = "\b91*9*\b"   
Dim input As String = "99 95 919 929 9119 9219 999 9919 91119"
For Each match As Match In Regex.Matches(input, pattern)
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next     
' The example displays the following output:   
'       '99' found at position 0.
'       '919' found at position 6.
'       '9119' found at position 14.
'       '999' found at position 24.
'       '91119' found at position 33.
string pattern = @"\b91*9*\b";   
string input = "99 95 919 929 9119 9219 999 9919 91119";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

// The example displays the following output:   
//       '99' found at position 0.
//       '919' found at position 6.
//       '9119' found at position 14.
//       '999' found at position 24.
//       '91119' found at position 33.

Il modello di espressione regolare viene definito come illustrato nella tabella riportata di seguito.

Modello

Oggetto di descrizione

\b

Iniziare dal confine di una parola.

91*

Corrisponde a un "9" seguito da zero o più caratteri "1".

9*

Corrisponde a zero o più caratteri "9".

\b

Terminare al confine di una parola.

Ottiene una corrispondenza una o più volte: +

Il quantificatore + trova una o più corrispondenze con l'elemento precedente. Equivale a {1,}. + è un quantificatore greedy il cui equivalente lazy è +?.

Ad esempio, l'espressione regolare \ban+\w*?\b tenta di trovare una corrispondenza con intere parole che iniziano con la lettera a seguita da una o più istanze della lettera n. Questa espressione regolare viene illustrata nell'esempio seguente. L'espressione regolare trova una corrispondenza con le parole an, annual, announcement e antique, mentre correttamente non la trova con autumn e all.

Dim pattern As String = "\ban+\w*?\b"

Dim input As String = "Autumn is a great time for an annual announcement to all antique collectors."
For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next   
' The example displays the following output:   
'       'an' found at position 27.
'       'annual' found at position 30.
'       'announcement' found at position 37.
'       'antique' found at position 57.      
string pattern = @"\ban+\w*?\b";

string input = "Autumn is a great time for an annual announcement to all antique collectors.";
foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

// The example displays the following output:   
//       'an' found at position 27.
//       'annual' found at position 30.
//       'announcement' found at position 37.
//       'antique' found at position 57.      

Il modello di espressione regolare viene definito come illustrato nella tabella riportata di seguito.

Modello

Oggetto di descrizione

\b

Iniziare dal confine di una parola.

an+

Corrisponde a una "a" seguita da uno o più caratteri "n".

\w*?

Ottiene zero o più volte la corrispondenza di un carattere alfanumerico, ma il minor numero di volte possibile.

\b

Terminare al confine di una parola.

Ottiene zero o una volta una corrispondenza: ?

Il quantificatore ? trova zero o una corrispondenza con l'elemento precedente. Equivale a {0,1}. ? è un quantificatore greedy il cui equivalente lazy è ??.

Ad esempio, l'espressione regolare \ban?\b tenta di trovare una corrispondenza con intere parole che iniziano con la lettera a seguita da zero o più istanze della lettera n. In altri termini, tenta di trovare una corrispondenza con le parole a e an. Questa espressione regolare viene illustrata nell'esempio seguente.

Dim pattern As String = "\ban?\b"
Dim input As String = "An amiable animal with a large snount and an animated nose."
For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next  
' The example displays the following output:   
'       'An' found at position 0.
'       'a' found at position 23.
'       'an' found at position 42.
string pattern = @"\ban?\b";
string input = "An amiable animal with a large snount and an animated nose.";
foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

// The example displays the following output:   
//        'An' found at position 0.
//        'a' found at position 23.
//        'an' found at position 42.

Il modello di espressione regolare viene definito come illustrato nella tabella riportata di seguito.

Modello

Oggetto di descrizione

\b

Iniziare dal confine di una parola.

an?

Corrisponde a una "a" seguita da zero o un carattere "n".

\b

Terminare al confine di una parola.

Ottiene una corrispondenza esatta n volte: {n}

Il quantificatore {n} corrisponde all'elemento precedente esattamente n volte, dove n è qualsiasi numero intero. {n} è un quantificatore greedy il cui equivalente lazy è {n}?.

Ad esempio, l'espressione regolare \b\d+\,\d{3}\b tenta di trovare una corrispondenza con un limite di parola seguito da una o più cifre decimali seguite da tre cifre decimali seguite da un limite di parola. Questa espressione regolare viene illustrata nell'esempio seguente.

Dim pattern As String = "\b\d+\,\d{3}\b"
Dim input As String = "Sales totaled 103,524 million in January, " + _
                      "106,971 million in February, but only " + _
                      "943 million in March."
For Each match As Match In Regex.Matches(input, pattern)
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next     
' The example displays the following output:   
'       '103,524' found at position 14.
'       '106,971' found at position 45.
string pattern = @"\b\d+\,\d{3}\b";
string input = "Sales totaled 103,524 million in January, " + 
                      "106,971 million in February, but only " + 
                      "943 million in March.";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

//  The example displays the following output:   
//        '103,524' found at position 14.
//        '106,971' found at position 45.

Il modello di espressione regolare viene definito come illustrato nella tabella riportata di seguito.

Modello

Oggetto di descrizione

\b

Iniziare dal confine di una parola.

\d+

Corrisponde a una o più cifre decimali.

\,

Corrisponde a una virgola.

\d{3}

Corrisponde a tre cifre decimali.

\b

Terminare al confine di una parola.

Ottiene una corrispondenza per almeno n volte: {n,}

Il quantificatore { n ,} corrisponde all'elemento precedente almeno n volte, dove n è qualsiasi numero intero. {n,} è un quantificatore greedy il cui equivalente lazy è {n}?.

Ad esempio, l'espressione regolare \b\d{2,}\b\D+ tenta di trovare una corrispondenza con un limite di parola seguito da almeno due cifre seguite da un limite di parola e da un carattere non numerico. Questa espressione regolare viene illustrata nell'esempio seguente. L'espressione regolare non trova corrispondenza con la frase "7 days" perché contiene solo uno cifra decimale, ma trova corrispondenza con le frasi "10 weeks and 300 years".

 Dim pattern As String = "\b\d{2,}\b\D+"  
 Dim input As String = "7 days, 10 weeks, 300 years"
For Each match As Match In Regex.Matches(input, pattern)
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next 
' The example displays the following output:
'       '10 weeks, ' found at position 8.
'       '300 years' found at position 18.
string pattern = @"\b\d{2,}\b\D+";   
string input = "7 days, 10 weeks, 300 years";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

//  The example displays the following output:
//        '10 weeks, ' found at position 8.
//        '300 years' found at position 18.

Il modello di espressione regolare viene definito come illustrato nella tabella riportata di seguito.

Modello

Oggetto di descrizione

\b

Iniziare dal confine di una parola.

\d{2,}

Corrisponde almeno a due cifre decimali.

\b

Trovare la corrispondenza di un confine di parola.

\D+

Corrisponde almeno a una cifra non decimale.

Corrispondenza tra n e m volte: {n,m}

Il quantificatore {n,m} corrisponde all'elemento precedente almeno n volte, ma non più di m volte, dove n e m sono numeri interi. {n,m} è un quantificatore greedy il cui equivalente lazy è {n,m}?.

Nell'esempio riportato di seguito, l'espressione regolare (00\s){2,4} tenta di trovare una corrispondenza tra due e quattro occorrenze di due cifre zero seguite da uno spazio. Si noti che la parte finale della stringa di input include il modello cinque volte anziché il massimo di quattro. Tuttavia, solo la parte iniziale della sottostringa (fino allo spazio e alla quinta coppia di zero) corrisponde al modello dell'espressione regolare.

Dim pattern As String = "(00\s){2,4}"
Dim input As String = "0x00 FF 00 00 18 17 FF 00 00 00 21 00 00 00 00 00"
For Each match As Match In Regex.Matches(input, pattern)
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next 
' The example displays the following output:
'       '00 00 ' found at position 8.
'       '00 00 00 ' found at position 23.
'       '00 00 00 00 ' found at position 35.
string pattern = @"(00\s){2,4}";
string input = "0x00 FF 00 00 18 17 FF 00 00 00 21 00 00 00 00 00";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

//  The example displays the following output:
//        '00 00 ' found at position 8.
//        '00 00 00 ' found at position 23.
//        '00 00 00 00 ' found at position 35.

Ottiene zero o più volte una corrispondenza (Corrispondenza Lazy): *?

Il quantificatore *? corrisponde all'elemento che lo precede zero o più volte, ma il numero minimo di volte possibile. Si tratta di un quantificatore lazy omologo del quantificatore greedy *.

Nell'esempio riportato di seguito, l'espressione regolare \b\w*?oo\w*?\b corrisponde a tutte le parole che contengono la stringa oo.

 Dim pattern As String = "\b\w*?oo\w*?\b"
 Dim input As String = "woof root root rob oof woo woe"
 For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
    Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
 Next 
 ' The example displays the following output:
'       'woof' found at position 0.
'       'root' found at position 5.
'       'root' found at position 10.
'       'oof' found at position 19.
'       'woo' found at position 23.
 string pattern = @"\b\w*?oo\w*?\b";
 string input = "woof root root rob oof woo woe";
 foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
    Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

 //  The example displays the following output:
//        'woof' found at position 0.
//        'root' found at position 5.
//        'root' found at position 10.
//        'oof' found at position 19.
//        'woo' found at position 23.

Il modello di espressione regolare viene definito come illustrato nella tabella riportata di seguito.

Modello

Oggetto di descrizione

\b

Iniziare dal confine di una parola.

\w*?

Corrisponde a zero o più caratteri alfanumerici, ma al minor numero di caratteri possibile.

oo

Corrisponde alla stringa "oo".

\w*?

Corrisponde a zero o più caratteri alfanumerici, ma al minor numero di caratteri possibile.

\b

Fine sul confine di parola.

Ottiene una corrispondenza una o più volte (Corrispondenza Lazy): +?

Il quantificatore +? corrisponde all'elemento che lo precede una o più volte, ma il numero minimo di volte possibile. Si tratta di un quantificatore lazy omologo del quantificatore greedy +.

Ad esempio, l'espressione regolare \b\w+?\b corrisponde a uno o più caratteri separati da limiti di parola. Questa espressione regolare viene illustrata nell'esempio seguente.

 Dim pattern As String = "\b\w+?\b"
 Dim input As String = "Aa Bb Cc Dd Ee Ff"
For Each match As Match In Regex.Matches(input, pattern)
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next 
' The example displays the following output:
'       'Aa' found at position 0.
'       'Bb' found at position 3.
'       'Cc' found at position 6.
'       'Dd' found at position 9.
'       'Ee' found at position 12.
'       'Ff' found at position 15.
string pattern = @"\b\w+?\b";
string input = "Aa Bb Cc Dd Ee Ff";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

//  The example displays the following output:
//        'Aa' found at position 0.
//        'Bb' found at position 3.
//        'Cc' found at position 6.
//        'Dd' found at position 9.
//        'Ee' found at position 12.
//        'Ff' found at position 15.

Ottiene zero o una volta una corrispondenza (Corrispondenza Lazy): ??

Il quantificatore ?? corrisponde all'elemento che lo precede zero o una volta, ma il numero minimo di volte possibile. Si tratta di un quantificatore lazy omologo del quantificatore greedy ?.

Ad esempio, l'espressione regolare ^\s*(System.)??Console.Write(Line)??\(?? tenta di far corrispondere le stringhe "Console.Write" o "Console.WriteLine". La stringa può includere anche "System." prima di "Console" e può essere seguita da una parentesi aperta. La stringa deve trovarsi all'inizio di una riga, anche se può essere preceduta da uno spazio vuoto. Questa espressione regolare viene illustrata nell'esempio seguente.

Dim pattern As String = "^\s*(System.)??Console.Write(Line)??\(??"
Dim input As String = "System.Console.WriteLine(""Hello!"")" + vbCrLf + _
                      "Console.Write(""Hello!"")" + vbCrLf + _
                      "Console.WriteLine(""Hello!"")" + vbCrLf + _
                      "Console.ReadLine()" + vbCrLf + _
                      "   Console.WriteLine"
For Each match As Match In Regex.Matches(input, pattern, _
                                         RegexOptions.IgnorePatternWhitespace Or RegexOptions.IgnoreCase Or RegexOptions.MultiLine)
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next 
' The example displays the following output:
'       'System.Console.Write' found at position 0.
'       'Console.Write' found at position 36.
'       'Console.Write' found at position 61.
'       '   Console.Write' found at position 110.
string pattern = @"^\s*(System.)??Console.Write(Line)??\(??";
string input = "System.Console.WriteLine(\"Hello!\")\n" + 
                      "Console.Write(\"Hello!\")\n" + 
                      "Console.WriteLine(\"Hello!\")\n" + 
                      "Console.ReadLine()\n" + 
                      "   Console.WriteLine";
foreach (Match match in Regex.Matches(input, pattern, 
                                      RegexOptions.IgnorePatternWhitespace | 
                                      RegexOptions.IgnoreCase | 
                                      RegexOptions.Multiline))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

//  The example displays the following output:
//        'System.Console.Write' found at position 0.
//        'Console.Write' found at position 36.
//        'Console.Write' found at position 61.
//        '   Console.Write' found at position 110.

Il modello di espressione regolare viene definito come illustrato nella tabella riportata di seguito.

Modello

Oggetto di descrizione

^

Corrisponde all'inizio del flusso di input.

\s*

Trovare la corrispondenza di zero o più spazi vuoti.

(System.)??

Corrisponde a zero o a un'occorrenza della stringa "System.".

Console.Write

Corrispondere stringa "Console.Write".

(Line)??

Corrispondere zero o una occorrenza della stringa "Line".

\(??

Corrisponde a zero o a un'occorrenza della parentesi di apertura.

Ottiene una corrispondenza esatta n volte (Corrispondenza Lazy): {n}?

Il quantificatore {n}? corrisponde all'elemento precedente esattamente n volte, dove n è qualsiasi numero intero. Si tratta di un quantificatore lazy omologo del quantificatore greedy {n}+.

Nell'esempio riportato di seguito, l'espressione regolare \b(\w{3,}?\.){2}?\w{3,}?\b viene utilizzata per identificare un indirizzo di sito Web. Corrisponde a "www.microsoft.com" e "msdn.microsoft.com", ma non corrisponde a "sitoweb" o "azienda.com".

 Dim pattern As String = "\b(\w{3,}?\.){2}?\w{3,}?\b"
 Dim input As String = "www.microsoft.com msdn.microsoft.com mywebsite mycompany.com"
For Each match As Match In Regex.Matches(input, pattern)
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next     
' The example displays the following output:
'       'www.microsoft.com' found at position 0.
'       'msdn.microsoft.com' found at position 18.
string pattern = @"\b(\w{3,}?\.){2}?\w{3,}?\b";
string input = "www.microsoft.com msdn.microsoft.com mywebsite mycompany.com";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

//  The example displays the following output:
//        'www.microsoft.com' found at position 0.
//        'msdn.microsoft.com' found at position 18.

Il modello di espressione regolare viene definito come illustrato nella tabella riportata di seguito.

Modello

Oggetto di descrizione

\b

Iniziare dal confine di una parola.

(\w{3,}? \.)

Corrisponde ad almeno 3 caratteri alfanumerici, ma al minor numero di caratteri possibile, seguiti da un punto. Equivale al primo gruppo di acquisizione.

(\w{3,}? \.){2}?

Ottiene due volte la corrispondenza per il modello nel primo gruppo, ma il minor numero di volte possibile.

\b

Termina la corrispondenza sul confine di parola.

Ottiene una corrispondenza per almeno n volte (Corrispondenza Lazy): {n,}?

Il quantificatore { n ,}? corrisponde all'elemento precedente almeno n volte, dove n è qualsiasi numero intero, ma il minor numero di volte possibile. Si tratta di un quantificatore lazy omologo del quantificatore greedy {n,}.

Vedere l'esempio relativo al quantificatore {n}? nella sezione precedente per un'illustrazione. L'espressione regolare nell'esempio utilizza il quantificatore {n,} per ottenere una corrispondenza con una stringa costituita da almeno tre caratteri seguiti da un punto.

Corrispondenza tra n e m volte (Corrispondenza Lazy): {n, m}?

Il quantificatore {n,m}? corrisponde all'elemento precedente tra n e m volte, dove n e m sono numeri interi, ma il minor numero di volte possibile. Si tratta di un quantificatore lazy omologo del quantificatore greedy {n,m}.

Nel seguente esempio, l'espressione regolare \b[A-Z](\w*\s+){1,10}?[.!?] corrisponde alle frasi che contengono da una a dieci parole. Corrisponde a tutte le frasi nella stringa di input ad eccezione di una singola frase che contenga 18 parole.

Dim pattern As String = "\b[A-Z](\w*\s?){1,10}?[.!?]"
Dim input As String = "Hi. I am writing a short note. Its purpose is " + _
                      "to test a regular expression that attempts to find " + _
                      "sentences with ten or fewer words. Most sentences " + _
                      "in this note are short."
For Each match As Match In Regex.Matches(input, pattern)
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next 
' The example displays the following output:
'       'Hi.' found at position 0.
'       'I am writing a short note.' found at position 4.
'       'Most sentences in this note are short.' found at position 132.
string pattern = @"\b[A-Z](\w*?\s*?){1,10}[.!?]";
string input = "Hi. I am writing a short note. Its purpose is " + 
                      "to test a regular expression that attempts to find " + 
                      "sentences with ten or fewer words. Most sentences " + 
                      "in this note are short.";
foreach (Match match in Regex.Matches(input, pattern))
   Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);

//  The example displays the following output:
//        'Hi.' found at position 0.
//        'I am writing a short note.' found at position 4.
//        'Most sentences in this note are short.' found at position 132.

Il modello di espressione regolare viene definito come illustrato nella tabella riportata di seguito.

Modello

Oggetto di descrizione

\b

Iniziare dal confine di una parola.

[A-Z]

Corrisponde a un carattere maiuscolo da A a Z.

(\w*\s+)

Corrisponde a zero o più caratteri alfanumerici, seguiti da uno o più spazi vuoti. Si tratta del primo gruppo di acquisizione.

{1,10}?

Ottiene da 1 a 10 volte la corrispondenza con il modello precedente, ma il minor numero di volte possibile.

[.!?]

Corrisponde a uno dei caratteri di punteggiatura ".", "!" o "?".

Quantificatore greedy e lazy

Diversi quantificatori sono disponibili in due versioni:

  • Una versione greedy.

    Un quantificatore greedy tenta di trovare una corrispondenza con un elemento il numero massimo di volte possibile.

  • Una versione non-greedy (o lazy).

    Un quantificatore non greedy tenta di trovare una corrispondenza con un elemento il numero minimo di volte possibile. È possibile trasformare un quantificatore greedy in un quantificatore lazy aggiungendo semplicemente un ?.

Considerare un'espressione regolare semplice progettata per estrarre le ultime quattro cifre da una stringa di numeri, ad esempio il numero di una carta di credito. La versione dell'espressione regolare che utilizza il quantificatore greedy * è \b.*([0-9]{4})\b. Tuttavia, se una stringa contiene due numeri, l'espressione regolare corrisponde soltanto alle ultime quattro cifre del secondo numero, come illustrato nell'esempio seguente.

Dim greedyPattern As String = "\b.*([0-9]{4})\b"
Dim input1 As String = "1112223333 3992991999"
For Each match As Match In Regex.Matches(input1, greedypattern)
   Console.WriteLine("Account ending in ******{0}.", match.Groups(1).Value)
Next
' The example displays the following output:
'       Account ending in ******1999.
string greedyPattern = @"\b.*([0-9]{4})\b";
string input1 = "1112223333 3992991999";
foreach (Match match in Regex.Matches(input1, greedyPattern))
   Console.WriteLine("Account ending in ******{0}.", match.Groups[1].Value);

// The example displays the following output:
//       Account ending in ******1999.

L'espressione regolare non riesce a trovare una corrispondenza con il primo numero perché il quantificatore * tenta di trovare una corrispondenza con l'elemento precedente il numero massimo di volte possibile nell'intera stringa, quindi trova la corrispondenza alla fine della stringa.

Non si tratta del comportamento previsto. È invece possibile utilizzare il quantificatore lazy *? per estrarre cifre da entrambi numeri, come illustrato nell'esempio seguente.

Dim lazyPattern As String = "\b.*?([0-9]{4})\b"
Dim input2 As String = "1112223333 3992991999"
For Each match As Match In Regex.Matches(input2, lazypattern)
   Console.WriteLine("Account ending in ******{0}.", match.Groups(1).Value)
Next     
' The example displays the following output:
'       Account ending in ******3333.
'       Account ending in ******1999.
string lazyPattern = @"\b.*?([0-9]{4})\b";
string input2 = "1112223333 3992991999";
foreach (Match match in Regex.Matches(input2, lazyPattern))
   Console.WriteLine("Account ending in ******{0}.", match.Groups[1].Value);

// The example displays the following output:
//       Account ending in ******3333.
//       Account ending in ******1999.

Nella maggior parte dei casi, le espressioni regolari con quantificatori greedy e lazy restituiscono le stesse corrispondenze. In genere restituiscono risultati diversi se utilizzate con il carattere jolly, metacarattere ., che corrisponde a qualsiasi carattere.

Quantificatori e corrispondenze vuote

I quantificatori *, + e {n,m} e le controparti lazy non si ripetono mai dopo una corrispondenza vuota quando è stato trovato il numero minimo di acquisizioni. Questa regola impedisce ai quantificatori di fornire cicli infiniti su corrispondenze di sottoespressioni vuote quando il numero massimo di acquisizioni di gruppo possibili è infinito o prossimo a tale valore.

Ad esempio, nel codice seguente viene illustrato il risultato di una chiamata al metodo Regex.Match con il modello di espressione regolare (a?)*, che corrisponde a zero o una occorrenza del carattere "a" per 0 o più volte. Si noti che il singolo gruppo di acquisizione acquisisce ogni "a", nonché String.Empty, ma non esiste una seconda corrispondenza vuota, perché la prima corrispondenza vuota induce il quantificatore a non essere ripetuto.

Imports System.Text.RegularExpressions

Module Example
   Public Sub Main()
      Dim pattern As String = "(a?)*"
      Dim input As String = "aaabbb"
      Dim match As Match = Regex.Match(input, pattern)
      Console.WriteLine("Match: '{0}' at index {1}", 
                        match.Value, match.Index)
      If match.Groups.Count > 1 Then
         Dim groups As GroupCollection = match.Groups
         For grpCtr As Integer = 1 To groups.Count - 1
            Console.WriteLine("   Group {0}: '{1}' at index {2}", 
                              grpCtr, 
                              groups(grpCtr).Value,
                              groups(grpCtr).Index)
            Dim captureCtr As Integer = 0
            For Each capture As Capture In groups(grpCtr).Captures
               captureCtr += 1
               Console.WriteLine("      Capture {0}: '{1}' at index {2}", 
                                 captureCtr, capture.Value, capture.Index)
            Next
         Next 
      End If   
   End Sub
End Module
' The example displays the following output:
'       Match: 'aaa' at index 0
'          Group 1: '' at index 3
'             Capture 1: 'a' at index 0
'             Capture 2: 'a' at index 1
'             Capture 3: 'a' at index 2
'             Capture 4: '' at index 3
using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = "(a?)*";
      string input = "aaabbb";
      Match match = Regex.Match(input, pattern);
      Console.WriteLine("Match: '{0}' at index {1}", 
                        match.Value, match.Index);
      if (match.Groups.Count > 1) {
         GroupCollection groups = match.Groups;
         for (int grpCtr = 1; grpCtr <= groups.Count - 1; grpCtr++) {
            Console.WriteLine("   Group {0}: '{1}' at index {2}", 
                              grpCtr, 
                              groups[grpCtr].Value,
                              groups[grpCtr].Index);
            int captureCtr = 0;
            foreach (Capture capture in groups[grpCtr].Captures) {
               captureCtr++;
               Console.WriteLine("      Capture {0}: '{1}' at index {2}", 
                                 captureCtr, capture.Value, capture.Index);
            }
         } 
      }   
   }
}
// The example displays the following output:
//       Match: 'aaa' at index 0
//          Group 1: '' at index 3
//             Capture 1: 'a' at index 0
//             Capture 2: 'a' at index 1
//             Capture 3: 'a' at index 2
//             Capture 4: '' at index 3

Per visualizzare la differenza pratica tra un gruppo di acquisizione che definisce un numero minimo e uno massimo di acquisizioni e uno che definisce un numero fisso di acquisizioni, considerare i modelli di espressione regolare (a\1|(?(1)\1)){0,2} e (a\1|(?(1)\1)){2}. Entrambe le espressioni regolari sono costituite da un singolo gruppo di acquisizione, che viene definito nel modo illustrato nella tabella seguente.

Modello

Oggetto di descrizione

(a\1

Far corrispondere "a" con il valore del primo gruppo acquisito…

|(?(1)

… o eseguire il test per verificare se è stato definito il gruppo acquisito per primo. (Notare che il costrutto (?(1) non definisce un gruppo di acquisizione).

\1))

Se il primo gruppo acquisito esiste, fargli corrispondere il suo valore. Se il gruppo non esiste, corrisponderà a String.Empty.

La prima espressione regolare tenta di far corrispondere questo modello tra zero e due volte; la seconda esattamente due volte. Poiché il primo modello raggiunge il numero minimo di didascalie con la prima didascalia di String.Empty, non ripete mai il tentativo di far corrispondere a\1; il quantificatore di {0,2} consente solo corrispondenze vuote nell'ultima iterazione. Al contrario, la seconda espressione regolare non corrisponde a "a" poiché valuta a\1 una seconda volta; il numero minimo di iterazioni, ovvero 2, impone la ripetizione del modulo di gestione dopo una corrispondenza vuota.

Imports System.Text.RegularExpressions

Module Example
   Public Sub Main()
      Dim pattern, input As String

      pattern = "(a\1|(?(1)\1)){0,2}"
      input = "aaabbb" 

      Console.WriteLine("Regex pattern: {0}", pattern)
      Dim match As Match = Regex.Match(input, pattern)
      Console.WriteLine("Match: '{0}' at position {1}.", 
                        match.Value, match.Index)
      If match.Groups.Count > 1 Then
         For groupCtr As Integer = 1 To match.Groups.Count - 1
            Dim group As Group = match.Groups(groupCtr)         
            Console.WriteLine("   Group: {0}: '{1}' at position {2}.", 
                              groupCtr, group.Value, group.Index)
            Dim captureCtr As Integer = 0
            For Each capture As Capture In group.Captures
               captureCtr += 1
               Console.WriteLine("      Capture: {0}: '{1}' at position {2}.", 
                                 captureCtr, capture.Value, capture.Index)
            Next   
         Next
      End If
      Console.WriteLine()

      pattern = "(a\1|(?(1)\1)){2}"
      Console.WriteLine("Regex pattern: {0}", pattern)
      match = Regex.Match(input, pattern)
         Console.WriteLine("Matched '{0}' at position {1}.", 
                           match.Value, match.Index)
      If match.Groups.Count > 1 Then
         For groupCtr As Integer = 1 To match.Groups.Count - 1
            Dim group As Group = match.Groups(groupCtr)         
            Console.WriteLine("   Group: {0}: '{1}' at position {2}.", 
                              groupCtr, group.Value, group.Index)
            Dim captureCtr As Integer = 0
            For Each capture As Capture In group.Captures
               captureCtr += 1
               Console.WriteLine("      Capture: {0}: '{1}' at position {2}.", 
                                 captureCtr, capture.Value, capture.Index)
            Next   
         Next
      End If
   End Sub
End Module
' The example displays the following output:
'       Regex pattern: (a\1|(?(1)\1)){0,2}
'       Match: '' at position 0.
'          Group: 1: '' at position 0.
'             Capture: 1: '' at position 0.
'       
'       Regex pattern: (a\1|(?(1)\1)){2}
'       Matched 'a' at position 0.
'          Group: 1: 'a' at position 0.
'             Capture: 1: '' at position 0.
'             Capture: 2: 'a' at position 0.
using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern, input;

      pattern = @"(a\1|(?(1)\1)){0,2}";
      input = "aaabbb"; 

      Console.WriteLine("Regex pattern: {0}", pattern);
      Match match = Regex.Match(input, pattern);
      Console.WriteLine("Match: '{0}' at position {1}.", 
                        match.Value, match.Index);
      if (match.Groups.Count > 1) {
         for (int groupCtr = 1; groupCtr <= match.Groups.Count - 1; groupCtr++)
         {
            Group group = match.Groups[groupCtr];         
            Console.WriteLine("   Group: {0}: '{1}' at position {2}.", 
                              groupCtr, group.Value, group.Index);
            int captureCtr = 0;
            foreach (Capture capture in group.Captures) {
               captureCtr++;
               Console.WriteLine("      Capture: {0}: '{1}' at position {2}.", 
                                 captureCtr, capture.Value, capture.Index);
            }   
         }
      }
      Console.WriteLine();

      pattern = @"(a\1|(?(1)\1)){2}";
      Console.WriteLine("Regex pattern: {0}", pattern);
      match = Regex.Match(input, pattern);
         Console.WriteLine("Matched '{0}' at position {1}.", 
                           match.Value, match.Index);
      if (match.Groups.Count > 1) {
         for (int groupCtr = 1; groupCtr <= match.Groups.Count - 1; groupCtr++)
         {
            Group group = match.Groups[groupCtr];         
            Console.WriteLine("   Group: {0}: '{1}' at position {2}.", 
                              groupCtr, group.Value, group.Index);
            int captureCtr = 0;
            foreach (Capture capture in group.Captures) {
               captureCtr++;
               Console.WriteLine("      Capture: {0}: '{1}' at position {2}.", 
                                 captureCtr, capture.Value, capture.Index);
            }   
         }
      }
   }
}
// The example displays the following output:
//       Regex pattern: (a\1|(?(1)\1)){0,2}
//       Match: '' at position 0.
//          Group: 1: '' at position 0.
//             Capture: 1: '' at position 0.
//       
//       Regex pattern: (a\1|(?(1)\1)){2}
//       Matched 'a' at position 0.
//          Group: 1: 'a' at position 0.
//             Capture: 1: '' at position 0.
//             Capture: 2: 'a' at position 0.

Vedere anche

Concetti

Elementi del linguaggio di espressioni regolari

Backtracking

Cronologia delle modifiche

Data

Cronologia

Motivo

Ottobre 2010

È stata aggiunta la sezione "Quantificatori e corrispondenze vuote".

Miglioramento delle informazioni.