Delen via


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 één of meer keer voor.
? ?? 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 processor voor reguliere expressies zoveel mogelijk voorkomens van bepaalde patronen matcht. Door het ?-karakter aan een kwantificator toe te voegen, wordt 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($"'{match.Value}' found at position {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.

Een of meerdere 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, annual, announcement en antique, en komt correct niet overeen met autumn 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($"'{match.Value}' found at position {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 gevolgd door een of meer n tekens.
\w*? Komt overeen met een woordteken nul of meer keren, maar zo weinig mogelijk.
\b Eindig bij een woordgrens.

Komt Nul of Eén Keer Overeen: ?

De ? kwantificator komt overeen met het voorgaande element nul of één keer. 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($"'{match.Value}' found at position {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 gulzige kwantificator waarvan het luie equivalent {n}? is.

Een reguliere expressie zoals \b\d+\,\d{3}\b probeert bijvoorbeeld een woordgrens te vinden, gevolgd door een of meer cijfers, gevolgd door drie cijfers, en weer 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($"'{match.Value}' found at position {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-teken.
\d{3} Komt overeen met drie decimalen.
\b Eindig bij een woordgrens.

Komt ten minste n keer voor: {n,}

De {n,} kwantificator komt ten minste n keer overeen met het voorgaande element, waarbij n een geheel getal is. { n,} is een gulzige 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($"'{match.Value}' found at position {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($"'{match.Value}' found at position {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($"'{match.Value}' found at position {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($"'{match.Value}' found at position {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 nul of één keer (Luie match): ??

De ?? kwantificator vergelijkt het voorgaande element nul of één keer, maar zo min mogelijk keren. 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 System. bevatten vóór Console, en kan gevolgd worden door een openend haakje. 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($"'{match.Value}' found at position {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 witruimtetekens.
(System.)?? Komt overeen met nul of één voorkomen van de tekenreeks System..
Console.Write Komt overeen met de tekenreeks Console.Write.
(Line)?? Komt overeen met nul of één voorkomen van de tekenreeks Line.
\(?? Komt overeen met nul of één keer van het openend haakje.

Exact n keer (lui patroon): {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($"'{match.Value}' found at position {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 vastlegger groep.
(\w{3,}?\.){2}? Komt twee keer overeen met het patroon in de eerste groep, maar probeert dit zo min mogelijk keer te doen.
\b Beëindig de wedstrijd op een woordgrens.

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

De {n,}? kwantificeerder komt overeen met het voorgaande element ten minste n keer, waarbij n een geheel getal is, maar zo weinig keren als 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 keer, waarbij n en m gehele getallen zijn, maar zo min 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($"'{match.Value}' found at position {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 min mogelijk. Dit patroon is de eerste vastlegger 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 gulzige kwantificator probeert een element zo vaak mogelijk te matchen.

  • Een niet-hebzuchtige (of luie) versie.

    Een niet-gulzige kwantor probeert een element zo weinig mogelijk keren te laten overeenkomen. U kunt een gretige kwantificator omzetten in een luie kwantificator door een ? toe te voegen.

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 ******{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 ******{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 lazy kwantificatoren dezelfde resultaten. 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 *, +, {n,m} en hun luie tegenhangers herhalen nooit na een lege match wanneer het minimum aantal vangsten is bereikt. 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: '{match.Value}' at index {match.Index}");
      if (match.Groups.Count > 1) {
         GroupCollection groups = match.Groups;
         for (int grpCtr = 1; grpCtr <= groups.Count - 1; grpCtr++) {
            Console.WriteLine($"   Group {grpCtr}: '{groups[grpCtr].Value}' at index {groups[grpCtr].Index}");
            int captureCtr = 0;
            foreach (Capture capture in groups[grpCtr].Captures) {
               captureCtr++;
               Console.WriteLine($"      Capture {captureCtr}: '{capture.Value}' at index {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 vastleggende groep die is gedefinieerd in de volgende tabel:

Patroon Beschrijving
(a\1 Ofwel komt overeen a met de waarde van de eerste vastgelegde groep ...
|(?(1) … of test of de eerste vastgelegde groep is gedefinieerd. De (?(1) construct definieert geen vastleggende groep.
\1)) Als de eerste vastgelegde groep bestaat, geef dan de bijbehorende waarde terug. Als de groep niet bestaat, komt de groep overeen met 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 zijn minimale aantal opnamen bereikt met zijn eerste opname van String.Empty, wordt het nooit herhaald om overeen te komen met a\1. De {0,2} kwantificator staat alleen lege overeenkomsten toe in de laatste iteratie. In tegenstelling daarmee komt de tweede reguliere expressie overeen met a omdat deze een tweede keer a\1 evalueert. Het minimum aantal iteraties, 2, dwingt het systeem om te herhalen na een lege match.

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: {pattern}");
      Match match = Regex.Match(input, pattern);
      Console.WriteLine($"Match: '{match.Value}' at position {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: {groupCtr}: '{group.Value}' at position {group.Index}.");
            int captureCtr = 0;
            foreach (Capture capture in group.Captures) {
               captureCtr++;
               Console.WriteLine($"      Capture: {captureCtr}: '{capture.Value}' at position {capture.Index}.");
            }
         }
      }
      Console.WriteLine();

      pattern = @"(a\1|(?(1)\1)){2}";
      Console.WriteLine($"Regex pattern: {pattern}");
      match = Regex.Match(input, pattern);
         Console.WriteLine($"Matched '{match.Value}' at position {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: {groupCtr}: '{group.Value}' at position {group.Index}.");
            int captureCtr = 0;
            foreach (Capture capture in group.Captures) {
               captureCtr++;
               Console.WriteLine($"      Capture: {captureCtr}: '{capture.Value}' at position {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