Kwantificatoren in reguliere expressies

Kwantificatoren geven aan hoeveel exemplaren van een teken,groep of tekenklasse aanwezig moeten zijn in de invoer om een overeenkomst te vinden. De volgende tabel bevat de kwantifiers die worden ondersteund door .NET:

Greedy kwantificator Luie kwantificator Beschrijving
* *? Komt overeen met nul of meer keren.
+ +? Komt overeen met een of meer keren.
? ?? Komt overeen met nul of één keer.
{N} {N}? Komt precies n keer overeen.
{N,} {N,}? Komt minstens n keer overeen.
{n,m} {n,m}? Komt overeen van n tot m tijden.

De hoeveelheden n en m zijn gehele getallen. Normaal gesproken zijn kwantificatoren hebzuchtig. Ze zorgen ervoor dat de engine voor reguliere expressies zoveel mogelijk exemplaren van bepaalde patronen matcht. Als u het ? teken toevoegt aan een kwantificator, is het lui. Het zorgt ervoor dat de engine voor reguliere expressies zo weinig mogelijk exemplaren matcht. Zie de sectie Greedy en Lazy Quantifiers verderop in dit artikel voor een volledige beschrijving van het verschil tussen hebzuchtige en luie kwantificatoren .

Belangrijk

Het nesten van kwantificatoren, zoals het reguliere expressiepatroon (a*)*, kan het aantal vergelijkingen verhogen dat de engine voor reguliere expressies moet uitvoeren. Het aantal vergelijkingen kan toenemen als exponentiële functie van het aantal tekens in de invoertekenreeks. Zie Backtracking voor meer informatie over dit gedrag en de bijbehorende tijdelijke oplossingen.

Kwantificatoren voor reguliere expressies

In de volgende secties worden de kwantificatoren vermeld die worden ondersteund door reguliere .NET-expressies:

Notitie

Als de tekens *, +, ?, {en } worden aangetroffen in een normaal expressiepatroon, interpreteert de reguliere expressie-engine deze als kwantificatoren of een deel van kwantificatorconstructies, tenzij ze zijn opgenomen in een tekenklasse. Als u deze wilt interpreteren als letterlijke tekens buiten een tekenklasse, moet u deze escapen door ze te laten voorafgaan met een backslash. De tekenreeks \* in een normaal expressiepatroon wordt bijvoorbeeld geïnterpreteerd als een letterlijk sterretje ('*').

Kom overeen met nul of meer keren: *

De * kwantificator komt overeen met het voorgaande element nul of meer keren. Het is gelijk aan de {0,} kwantificator. * is een hebzuchtige kwantificator waarvan het luie equivalent is *?.

In het volgende voorbeeld ziet u deze reguliere expressie. Vijf van de negen cijfergroepen in de invoertekenreeks komen overeen met het patroon en vier (95, 9299219, en 9919) komen niet overeen.

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.

Het patroon voor reguliere expressies wordt gedefinieerd zoals wordt weergegeven in de volgende tabel:

Patroon Beschrijving
\b Hiermee geeft u op dat de overeenkomst moet beginnen bij een woordgrens.
91* Komt overeen met een 9 gevolgd door nul of meer 1 tekens.
9* Komt overeen met nul of meer 9 tekens.
\b Hiermee geeft u op dat de overeenkomst moet eindigen op een woordgrens.

Komt overeen met een of meer keren: +

De + kwantificator komt een of meer keren overeen met het voorgaande element. Het is gelijk aan {1,}. + is een hebzuchtige kwantificator waarvan het luie equivalent is +?.

De reguliere expressie \ban+\w*?\b probeert bijvoorbeeld volledige woorden te vinden die beginnen met de letter a , gevolgd door een of meer exemplaren van de letter n. In het volgende voorbeeld ziet u deze reguliere expressie. De reguliere expressie komt overeen met de woorden an, announcementannualen , en antiquekomt niet overeen autumn met en 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.

Het patroon voor reguliere expressies wordt gedefinieerd zoals wordt weergegeven in de volgende tabel:

Patroon Beschrijving
\b Begin bij een woordgrens.
an+ Komt overeen met een a of meer n tekens.
\w*? Komt overeen met een woordteken nul of meer keren, maar zo weinig mogelijk.
\b Eindig bij een woordgrens.

Match Zero of One Time: ?

De ? kwantificator komt overeen met het voorgaande element nul of eenmalig. Het is gelijk aan {0,1}. ? is een hebzuchtige kwantificator waarvan het luie equivalent is ??.

De reguliere expressie \ban?\b probeert bijvoorbeeld volledige woorden te vinden die beginnen met de letter a gevolgd door nul of één exemplaar van de letter n. Met andere woorden, het probeert overeen te komen met de woorden a en an. In het volgende voorbeeld ziet u deze reguliere expressie:

string pattern = @"\ban?\b";
string input = "An amiable animal with a large snout 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 snout 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.

Het patroon voor reguliere expressies wordt gedefinieerd zoals wordt weergegeven in de volgende tabel:

Patroon Beschrijving
\b Begin bij een woordgrens.
an? Komt overeen met een a gevolgd door nul of één n teken.
\b Eindig bij een woordgrens.

Exact n keer overeenkomen: {n}

De {n} kwantificator komt exact overeen met het voorgaande element exact n keer, waarbij n een geheel getal is. {n is een greedy kwantificator waarvan het luie equivalent n}? is{.}

De reguliere expressie \b\d+\,\d{3}\b probeert bijvoorbeeld een woordgrens te vinden, gevolgd door een of meer decimale cijfers gevolgd door drie decimale cijfers gevolgd door een woordgrens. In het volgende voorbeeld ziet u deze reguliere expressie:

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.

Het patroon voor reguliere expressies wordt gedefinieerd zoals wordt weergegeven in de volgende tabel:

Patroon Beschrijving
\b Begin bij een woordgrens.
\d+ Komt overeen met een of meer decimale cijfers.
\, Komt overeen met een komma.
\d{3} Komt overeen met drie decimalen.
\b Eindig bij een woordgrens.

Komt ten minste n keer overeen: {n,}

De {n,} kwantificator komt ten minste n keer overeen met het voorgaande element, waarbij n een geheel getal is. {n is een greedy kwantificator waarvan het luie equivalent n,}? is{.,}

De reguliere expressie \b\d{2,}\b\D+ probeert bijvoorbeeld een woordgrens te vinden, gevolgd door ten minste twee cijfers gevolgd door een woordgrens en een niet-cijferig teken. In het volgende voorbeeld ziet u deze reguliere expressie. De reguliere expressie komt niet overeen met de woordgroep "7 days" omdat deze slechts één decimaalteken bevat, maar wel overeenkomt met de woordgroepen "10 weeks" en "300 years".

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.

Het patroon voor reguliere expressies wordt gedefinieerd zoals wordt weergegeven in de volgende tabel:

Patroon Beschrijving
\b Begin bij een woordgrens.
\d{2,} Komt overeen met ten minste twee decimale cijfers.
\b Komt overeen met een woordgrens.
\D+ Komt overeen met ten minste één niet-decimaal cijfer.

Overeenkomst tussen n en m tijden: {n,m}

De {n,m-kwantificator} komt ten minste n keer overeen met het voorgaande element, maar niet meer dan m keer, waarbij n en m gehele getallen zijn. {n,m} is een hebzuchtige kwantificator waarvan het luie equivalent n m,}? is.{

In het volgende voorbeeld probeert de reguliere expressie (00\s){2,4} overeen te komen tussen twee en vier exemplaren van twee nul cijfers, gevolgd door een spatie. Het laatste gedeelte van de invoertekenreeks bevat dit patroon vijf keer in plaats van het maximum van vier. Alleen het eerste gedeelte van deze subtekenreeks (tot aan de spatie en het vijfde paar nullen) komt echter overeen met het reguliere expressiepatroon.

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.

Kom overeen met nul of meer tijden (luie overeenkomst): *?

De *? kwantificator komt overeen met het voorgaande element nul of meer keren, maar zo weinig mogelijk. Het is de luie tegenhanger van de hebzuchtige kwantificator *.

In het volgende voorbeeld komt de reguliere expressie \b\w*?oo\w*?\b overeen met alle woorden die de tekenreeks oobevatten.

 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.

Het patroon voor reguliere expressies wordt gedefinieerd zoals wordt weergegeven in de volgende tabel:

Patroon Beschrijving
\b Begin bij een woordgrens.
\w*? Komt overeen met nul of meer woordtekens, maar zo weinig mogelijk tekens.
oo Komt overeen met de tekenreeks oo.
\w*? Komt overeen met nul of meer woordtekens, maar zo weinig mogelijk tekens.
\b Eindig op een woordgrens.

Een of meer keren vergelijken (luie overeenkomst): +?

De +? kwantificator komt een of meer keer overeen met het voorgaande element, maar zo weinig mogelijk. Het is de luie tegenhanger van de hebzuchtige kwantificator +.

De reguliere expressie \b\w+?\b komt bijvoorbeeld overeen met een of meer tekens, gescheiden door woordgrenzen. In het volgende voorbeeld ziet u deze reguliere expressie:

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.

Match Zero of One Time (Luie overeenkomst): ??

De ?? kwantificator komt overeen met het voorgaande element nul of één keer, maar zo weinig mogelijk. Het is de luie tegenhanger van de hebzuchtige kwantificator ?.

De reguliere expressie ^\s*(System.)??Console.Write(Line)??\(?? probeert bijvoorbeeld overeen te komen met de tekenreeksen Console.Write of Console.WriteLine. De tekenreeks kan ook eerder Consoleworden opgenomen System. en kan worden gevolgd door een haakje openen. De tekenreeks moet aan het begin van een regel staan, hoewel deze kan worden voorafgegaan door witruimte. In het volgende voorbeeld ziet u deze reguliere expressie:

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.

Het patroon voor reguliere expressies wordt gedefinieerd zoals wordt weergegeven in de volgende tabel:

Patroon Beschrijving
^ Komt overeen met het begin van de invoerstroom.
\s* Komt overeen met nul of meer spatietekens.
(System.)?? Komt overeen met nul of één exemplaar van de tekenreeks System..
Console.Write Komt overeen met de tekenreeks Console.Write.
(Line)?? Komt overeen met nul of één exemplaar van de tekenreeks Line.
\(?? Komt overeen met nul of één exemplaar van het haakje openen.

Exact n tijden (luie overeenkomst): {n}?

De {n}? kwantificator komt exact n overeen met het voorgaande element, waarbij n een geheel getal is. Het is de luie tegenhanger van de hebzuchtige kwantificator {n}.

In het volgende voorbeeld wordt de reguliere expressie \b(\w{3,}?\.){2}?\w{3,}?\b gebruikt om een websiteadres te identificeren. De expressie komt overeen www.microsoft.com en msdn.microsoft.com maar komt niet overeen mywebsite of 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.

Het patroon voor reguliere expressies wordt gedefinieerd zoals wordt weergegeven in de volgende tabel:

Patroon Beschrijving
\b Begin bij een woordgrens.
(\w{3,}?\.) Komt overeen met ten minste drie woordtekens, maar zo weinig mogelijk tekens, gevolgd door een punt of puntteken. Dit patroon is de eerste vastleggende groep.
(\w{3,}?\.){2}? Komt twee keer overeen met het patroon in de eerste groep, maar zo weinig mogelijk.
\b Beëindig de overeenkomst op een woordgrens.

Komt ten minste n keer overeen (luie overeenkomst): {n,}?

De {n,}? kwantificeerder komt ten minste n overeen met het voorgaande element, waarbij n een geheel getal is, maar zo weinig mogelijk. Het is de luie tegenhanger van de hebzuchtige kwantificator {n,}.

Zie het voorbeeld voor de {n}? kwantificator in de vorige sectie voor een afbeelding. De reguliere expressie in dat voorbeeld gebruikt de {n,} kwantificator om overeen te komen met een tekenreeks met ten minste drie tekens gevolgd door een punt.

Overeenkomst tussen n en m times (luie overeenkomst): {n,m}?

De {n,m-kwantificator}? komt overeen met het voorgaande element tussen n en m tijden, waarbij n en m gehele getallen zijn, maar zo weinig mogelijk. Het is de luie tegenhanger van de hebzuchtige kwantificator {n,m.}

In het volgende voorbeeld komt de reguliere expressie \b[A-Z](\w*?\s*?){1,10}[.!?] overeen met zinnen die tussen 1 en 10 woorden bevatten. Deze komt overeen met alle zinnen in de invoertekenreeks, met uitzondering van één zin die 18 woorden bevat.

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.

Het patroon voor reguliere expressies wordt gedefinieerd zoals wordt weergegeven in de volgende tabel:

Patroon Beschrijving
\b Begin bij een woordgrens.
[A-Z] Komt overeen met een hoofdletter van A tot Z.
(\w*?\s*?) Komt overeen met nul of meer woordtekens, gevolgd door een of meer spatietekens, maar zo weinig mogelijk. Dit patroon is de eerste vastleggende groep.
{1,10} Komt overeen met het vorige patroon tussen 1 en 10 keer.
[.!?] Komt overeen met een van de interpunctietekens ., !of ?.

Greedy en Luie Kwantificatoren

Sommige kwantificatoren hebben twee versies:

  • Een hebzuchtige versie.

    Een greedy kwantificator probeert zo vaak mogelijk een element te vinden.

  • Een niet-hebzuchtige (of luie) versie.

    Een niet-greedy kwantificator probeert zo weinig mogelijk een element te vinden. U kunt een hebzuchtige kwantificator omzetten in een luie kwantificator door een ?.

Overweeg een reguliere expressie die is bedoeld om de laatste vier cijfers te extraheren uit een reeks getallen, zoals een creditcardnummer. De versie van de reguliere expressie die gebruikmaakt van de * greedy kwantificator is \b.*([0-9]{4})\b. Als een tekenreeks echter twee getallen bevat, komt deze reguliere expressie alleen overeen met de laatste vier cijfers van het tweede getal, zoals in het volgende voorbeeld wordt weergegeven:

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.

De reguliere expressie komt niet overeen met het eerste getal omdat de * kwantificator het vorige element zo vaak mogelijk in de hele tekenreeks probeert te vinden, zodat de overeenkomst aan het einde van de tekenreeks wordt gevonden.

Dit gedrag is niet het gewenste gedrag. In plaats daarvan kunt u de *? luie kwantificator gebruiken om cijfers uit beide getallen te extraheren, zoals in het volgende voorbeeld wordt weergegeven:

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.

In de meeste gevallen retourneren reguliere expressies met greedy en luie kwantificatoren dezelfde overeenkomsten. Ze retourneren meestal verschillende resultaten wanneer ze worden gebruikt met het jokerteken (.) metacharacter, dat overeenkomt met een willekeurig teken.

Kwantificatoren en lege overeenkomsten

De kwantificatoren*, +en {n,m} en hun luie tegenhangers herhalen nooit na een lege overeenkomst wanneer het minimum aantal vangsten is gevonden. Deze regel voorkomt dat kwantificatoren oneindige lussen invoeren voor lege subexpressie wanneer het maximum aantal mogelijke groepsopnamen oneindig of bijna oneindig is.

De volgende code toont bijvoorbeeld het resultaat van een aanroep naar de Regex.Match methode met het reguliere expressiepatroon (a?)*, dat overeenkomt met nul of één a teken nul of meer keren. De enkele vastleggende groep legt elk a en String.Empty, maar er is geen tweede lege overeenkomst omdat de eerste lege overeenkomst ervoor zorgt dat de kwantificator stopt met herhalen.

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

Als u het praktische verschil wilt zien tussen een vastleggende groep die een minimum- en maximumaantal opnamen definieert en een groep die een vast aantal opnamen definieert, moet u rekening houden met de reguliere expressiepatronen (a\1|(?(1)\1)){0,2} en (a\1|(?(1)\1)){2}. Beide reguliere expressies bestaan uit één groep die wordt vastgelegd in de volgende tabel:

Patroon Beschrijving
(a\1 Beide komt overeen a met de waarde van de eerste vastgelegde groep ...
|(?(1) ... of test of de eerste vastgelegde groep is gedefinieerd. De (?(1) constructie definieert geen vastleggende groep.
\1)) Als de eerste vastgelegde groep bestaat, komt u overeen met de bijbehorende waarde. Als de groep niet bestaat, komt de groep overeen String.Empty.

De eerste reguliere expressie probeert dit patroon tussen nul en twee keer te vinden; de tweede, precies twee keer. Omdat het eerste patroon het minimale aantal opnamen bereikt met de eerste opname String.Emptyvan , wordt het nooit herhaald om te proberen overeen te komen a\1. De {0,2} kwantificator staat alleen lege overeenkomsten toe in de laatste iteratie. De tweede reguliere expressie komt daarentegen overeen a omdat deze een tweede keer evalueert a\1 . Het minimum aantal iteraties, 2, dwingt de motor af te herhalen na een lege overeenkomst.

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.

Zie ook