quantificatori in espressioni regolari

I quantificatori specificano il numero di istanze di un carattere, un gruppo o una classe di caratteri che deve essere presente nell'input affinché venga trovata una corrispondenza. La tabella seguente elenca i quantificatori supportati da .NET:

Quantificatore greedy Quantificatore lazy Descrizione
* *? Corrisponde a zero o più volte.
+ +? Corrisponde a una o più volte.
? ?? Corrisponde a zero o una volta.
{N} {N}? Corrisponde esattamente n volte.
{N,} {N,}? Corrisponde almeno n volte.
{N,M} {N,M}? Corrisponde da n a m volte.

Le quantità n e m sono costanti integer. In genere, i quantificatori sono avidi. Determinano che il motore delle espressioni regolari corrisponda al maggior numero possibile di occorrenze di modelli specifici. L'aggiunta del ? carattere a un quantificatore lo rende lazy. Fa sì che il motore delle espressioni regolari corrisponda al minor numero possibile di occorrenze. Per una descrizione completa della differenza tra quantificatori greedy e lazy, vedere la sezione Quantificatori Greedy e Lazy più avanti in questo articolo.

Importante

I quantificatori di annidamento, ad esempio il criterio (a*)*di espressione regolare , possono aumentare il numero di confronti che il motore delle espressioni regolari deve eseguire. Il numero di confronti può aumentare come funzione esponenziale del numero di caratteri nella stringa di input. Per altre informazioni su questo comportamento e sulle relative soluzioni alternative, vedere Backtracking.

Quantificatori delle espressioni regolari

Le sezioni seguenti elencano i quantificatori supportati dalle espressioni regolari .NET:

Nota

Se vengono rilevati i caratteri *, +,?, { e} in un criterio di espressione regolare, il motore delle espressioni regolari li interpreta come quantificatori o parte di costrutti di quantificatori a meno che non siano inclusi in una classe di caratteri. Per interpretarli come caratteri letterali all'esterno di una classe di caratteri, è necessaria una sequenza di escape con i caratteri preceduti da una barra rovesciata. Ad esempio, la stringa \* in un'espressione regolare viene interpretata come carattere letterale asterisco ("*").

Trova la corrispondenza zero o più volte: *

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

L'esempio seguente illustra questa espressione regolare. Cinque dei nove gruppi di cifre nella stringa di input corrispondono al modello e quattro (95, 929, 9219e 9919) non corrispondono.

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

Il modello di espressione regolare è definito come illustrato nella tabella seguente:

Modello Descrizione
\b Specifica che la corrispondenza deve iniziare da un limite di parola.
91* Trova la corrispondenza con un oggetto 9 seguito da zero o più 1 caratteri.
9* Trova la corrispondenza con zero o più 9 caratteri.
\b Specifica che la corrispondenza deve terminare in corrispondenza di un limite di parola.

Trova la corrispondenza una o più volte: +

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

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

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

Il modello di espressione regolare è definito come illustrato nella tabella seguente:

Modello Descrizione
\b Inizia dal confine di una parola.
an+ Trova la corrispondenza con un oggetto a seguito da uno o più n caratteri.
\w*? Trova la corrispondenza con un carattere di parola zero o più volte, ma il minor numero di volte possibile.
\b Terminare al confine di una parola.

Trova la corrispondenza zero o una volta: ?

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

Ad esempio, l'espressione \ban?\b regolare tenta di trovare la corrispondenza con intere parole che iniziano con la lettera a seguita da zero o da un'istanza della lettera n. In altre parole, tenta di trovare la corrispondenza con le parole a e an. L'esempio seguente illustra questa espressione regolare:

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

Il modello di espressione regolare è definito come illustrato nella tabella seguente:

Modello Descrizione
\b Inizia dal confine di una parola.
an? Trova la corrispondenza con un carattere a seguito da zero o da un n carattere.
\b Terminare al confine di una parola.

Trova la corrispondenza esatta n volte: {n}

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

Ad esempio, l'espressione regolare \b\d+\,\d{3}\b tenta di trovare la corrispondenza con il confine di una parola seguito da una o più cifre decimali seguite da tre cifre decimali seguite dal confine di una parola. L'esempio seguente illustra questa espressione regolare:

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

Il modello di espressione regolare è definito come illustrato nella tabella seguente:

Modello Descrizione
\b Inizia dal confine di una parola.
\d+ Trova la corrispondenza con una o più cifre decimali.
\, Trova la corrispondenza con un carattere virgola.
\d{3} Trova la corrispondenza con tre cifre decimali.
\b Terminare al confine di una parola.

Trova la corrispondenza almeno n volte: {n,}

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

Ad esempio, l'espressione regolare \b\d{2,}\b\D+ tenta di trovare la corrispondenza con il confine di una parola seguito da almeno due cifre seguite dal confine di una parola e un carattere non numerico. L'esempio seguente illustra questa espressione regolare. L'espressione regolare non corrisponde alla frase "7 days" perché contiene una sola cifra decimale, ma corrisponde correttamente alle frasi "10 weeks" e "300 years"a .

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

Il modello di espressione regolare è definito come illustrato nella tabella seguente:

Modello Descrizione
\b Inizia dal confine di una parola.
\d{2,} Trova la corrispondenza con almeno due cifre decimali.
\b Corrisponde a un limite di parola.
\D+ Corrisponde a almeno una cifra non decimale.

Trova la 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 interi. {N,m} è un quantificatore greedy il cui equivalente lazy è {n,m}?.

Nell'esempio seguente, 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. La parte finale della stringa di input include questo modello cinque volte anziché il massimo di quattro. Tuttavia, solo la parte iniziale della sottostringa (fino allo spazio e alla quinta coppia di zeri) corrisponde al criterio dell'espressione regolare.

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

Trova la corrispondenza zero o più volte (corrispondenza lazy): *?

Il *? quantificatore corrisponde all'elemento precedente zero o più volte, ma il minor numero possibile. È la controparte lazy del quantificatore *greedy .

Nell'esempio seguente l'espressione regolare \b\w*?oo\w*?\b corrisponde a tutte le parole contenenti la stringa oo.

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

Il modello di espressione regolare è definito come illustrato nella tabella seguente:

Modello Descrizione
\b Inizia dal confine di una parola.
\w*? Corrisponde a zero o più caratteri di parola, ma il minor numero possibile di caratteri.
oo Corrisponde alla stringa oo.
\w*? Corrisponde a zero o più caratteri di parola, ma il minor numero possibile di caratteri.
\b Termina al confine di una parola.

Trova la corrispondenza una o più volte (corrispondenza lazy): +?

Il +? quantificatore corrisponde all'elemento precedente una o più volte, ma il minor numero possibile. È la controparte lazy del quantificatore +greedy .

Ad esempio, l'espressione regolare \b\w+?\b trova la corrispondenza con uno o più caratteri separati confini di parole. Nell'esempio seguente viene illustrata questa espressione regolare:

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

Trova la corrispondenza zero o una volta (corrispondenza lazy): ??

Il ?? quantificatore corrisponde allo zero dell'elemento precedente o una sola volta, ma il minor numero possibile. È la controparte lazy del quantificatore ?greedy .

Ad esempio, l'espressione ^\s*(System.)??Console.Write(Line)??\(?? regolare tenta di corrispondere alle stringhe Console.Write o Console.WriteLinea . La stringa può anche includere System. prima Consoledi e può essere seguita da una parentesi di apertura. La stringa deve essere all'inizio di una riga, anche se può essere preceduta da uno spazio vuoto. Nell'esempio seguente viene illustrata questa espressione regolare:

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

Il modello di espressione regolare è definito come illustrato nella tabella seguente:

Modello Descrizione
^ Corrisponde all'inizio del flusso di input.
\s* Corrisponde a zero o più caratteri di spazio vuoto.
(System.)?? Corrisponde a zero o una occorrenza della stringa System..
Console.Write Corrisponde alla stringa Console.Write.
(Line)?? Corrisponde a zero o una occorrenza della stringa Line.
\(?? Corrisponde a zero o una occorrenza della parentesi di apertura.

Trova la corrispondenza esatta n volte (corrispondenza lazy): {n}?

Il { quantificatore n}? corrisponde esattamente n all'elemento precedente, dove n è qualsiasi intero. È la controparte lazy del quantificatore { greedy n}.

Nell'esempio seguente viene usata l'espressione \b(\w{3,}?\.){2}?\w{3,}?\b regolare per identificare un indirizzo del sito Web. L'espressione corrisponde www.microsoft.com e msdn.microsoft.com ma non corrisponde mywebsite o mycompany.com.

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

Il modello di espressione regolare è definito come illustrato nella tabella seguente:

Modello Descrizione
\b Inizia dal confine di una parola.
(\w{3,}?\.) Corrisponde a almeno tre caratteri di parola, ma il minor numero possibile di caratteri, seguiti da un carattere punto o punto. Questo modello è il primo gruppo di acquisizione.
(\w{3,}?\.){2}? Corrisponde al modello nel primo gruppo due volte, ma il minor numero possibile.
\b Termina la corrispondenza sul confine di parola.

Trova la corrispondenza almeno n volte (corrispondenza lazy): {n,}?

Il { quantificatore n,}? corrisponde almeno all'elemento n precedente, dove n è qualsiasi intero, ma meno volte possibile. È la controparte lazy del quantificatore { greedy n,}.

Vedere l'esempio per il { quantificatore n}? nella sezione precedente per un'illustrazione. L'espressione regolare in questo esempio usa il { quantificatore n,} per corrispondere a una stringa con almeno tre caratteri seguiti da un punto.

Trova la 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 interi, ma il minor numero possibile. È la controparte lazy del quantificatore { greedy n,m}.

Nell'esempio seguente l'espressione \b[A-Z](\w*?\s*?){1,10}[.!?] regolare corrisponde alle frasi che contengono tra 1 e 10 parole. Trova la corrispondenza con tutte le frasi nella stringa di input, ad eccezione di una frase che contiene 18 parole.

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

Il modello di espressione regolare è definito come illustrato nella tabella seguente:

Modello Descrizione
\b Inizia dal confine di una parola.
[A-Z] Corrisponde a un carattere maiuscolo da A a Z.
(\w*?\s*?) Corrisponde a zero o più caratteri di parola, seguiti da uno o più caratteri di spazio vuoto, ma meno volte possibile. Questo modello è il primo gruppo di acquisizione.
{1,10} Corrisponde al modello precedente compreso tra 1 e 10 volte.
[.!?] Corrisponde a uno dei caratteri .di punteggiatura , !o ?.

Quantificatori greedy e lazy

Alcuni quantifier hanno due versioni:

  • Una versione greedy.

    Un quantificatore greedy tenta di trovare la corrispondenza con un elemento il maggior numero di volte possibile.

  • Una versione non greedy (o lazy).

    Un quantificatore non greedy tenta di trovare la corrispondenza con un elemento il minor numero di volte possibile. È possibile trasformare un quantificatore greedy in un quantificatore lazy aggiungendo un ?oggetto .

Prendere in considerazione un'espressione regolare destinata a estrarre le ultime quattro cifre da una stringa di numeri, ad esempio un numero di carta di credito. La versione dell'espressione regolare che usa il quantificatore greedy * è \b.*([0-9]{4})\b. Tuttavia, se una stringa contiene due numeri, questa espressione regolare corrisponde alle ultime quattro cifre del secondo numero solo, come illustrato nell'esempio seguente:

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

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

Questo comportamento non è quello desiderato. È invece possibile usare il quantificatore lazy per estrarre cifre da entrambi i numeri, come illustrato nell'esempio *? seguente:

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

Nella maggior parte dei casi le espressioni regolari con quantificatori greedy e lazy restituiscono le stesse corrispondenze. Restituiscono più comunemente risultati diversi quando vengono usati con la metacharacter (.) jolly, che corrisponde a qualsiasi carattere.

Quantificatori e corrispondenze vuote

I quantifier *, +e n,m} e { le loro controparti lazy non si ripetano mai dopo una corrispondenza vuota quando è stato trovato il numero minimo di acquisizioni. Questa regola impedisce ai quantificatori di avviare cicli infiniti su corrispondenze di sottoespressioni vuote quando il numero massimo di acquisizioni possibili per il gruppo possibili è infinito o quasi infinito.

Ad esempio, il codice seguente mostra il risultato di una chiamata al metodo con il modello (a?)*di espressione regolare , che corrisponde a Regex.Match zero o uno a zero carattere o più volte. Il singolo gruppo di acquisizione acquisisce ogni a oggetto e String.Empty, ma non esiste una seconda corrispondenza vuota perché la prima corrispondenza vuota causa l'arresto della ripetizione del quantificatore.

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

Per vedere in pratica la differenza tra un gruppo di acquisizione che definisce un numero minimo e massimo di acquisizioni e uno che definisce un numero fisso di acquisizioni, considerare i criteri 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, definito nella tabella seguente:

Modello Descrizione
(a\1 Entrambe le corrispondenze a insieme al valore del primo gruppo acquisito ...
|(?(1) … o verifica se il primo gruppo acquisito è stato definito. Il (?(1) costrutto non definisce un gruppo di acquisizione.
\1)) Se il primo gruppo acquisito esiste, trovare la corrispondenza con il relativo valore. Se il gruppo non esiste, il gruppo corrisponderà String.Emptya .

La prima espressione regolare tenta di trovare la corrispondenza con questo criterio da zero a due volte, la seconda esattamente due volte. Poiché il primo modello raggiunge il numero minimo di acquisizioni con la prima acquisizione di String.Empty, non ripete mai di provare a trovare la corrispondenza a\1con . Il {0,2} quantificatore consente solo corrispondenze vuote nell'ultima iterazione. Al contrario, la seconda espressione regolare corrisponde a perché valuta a\1 una seconda volta. Il numero minimo di iterazioni, 2, forza la ripetizione del motore dopo una corrispondenza vuota.

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

Vedi anche