Sdílet prostřednictvím


Kvantifikátory v regulárních výrazech

Kvantifikátory určují, kolik instancí znaku, skupiny nebo třídy znaků musí být ve vstupu, aby byla nalezena shoda. Následující tabulka uvádí kvantifikátory podporované rozhraním .NET:

Kvantifikátor greedy Opožděný kvantifikátor Popis
* *? Odpovídá nule nebo vícekrát.
+ +? Odpovídá jednou nebo vícekrát.
? ?? Odpovídá nule nebo jednou.
{n } {n }? Odpovídá přesně nkrát .
{n ,} {n ,}? Odpovídá alespoň nkrát .
{n , m } {n , m }? Odpovídá od n do m krát.

n Množství a m jsou celočíselné konstanty. Kvantifikátory jsou obvykle greedy. Způsobí, že modul regulárních výrazů bude odpovídat co nejvíce výskytům konkrétních vzorů. Připojením znaku ? k kvantifikátoru je opožděný. Způsobí, že modul regulárních výrazů bude odpovídat co nejméně výskytům. Úplný popis rozdílu mezi greedy a opožděnými kvantifikátory najdete v části Greedy a Lazy Kvantifikátory dále v tomto článku.

Důležité

Vnoření kvantifikátorů, jako je vzor (a*)*regulárního výrazu, může zvýšit počet porovnání, které musí modul regulárních výrazů provést. Počet porovnání se může zvýšit jako exponenciální funkce počtu znaků ve vstupním řetězci. Další informace o tomto chování a jeho alternativních řešeních najdete v tématu Navracení.

Kvantifikátory regulárních výrazů

Následující části uvádějí kvantifikátory podporované regulárními výrazy .NET:

Poznámka:

Pokud jsou znaky *, +, ?, {a } zjištěny ve vzoru regulárního výrazu, modul regulárních výrazů je interpretuje jako kvantifikátory nebo část konstruktorů kvantifikátoru, pokud nejsou zahrnuty do třídy znaků. Chcete-li je interpretovat jako literální znaky mimo třídu znaků, musíte je předcházet zpětným lomítkem. Například řetězec \* v vzoru regulárního výrazu se interpretuje jako literálový znak hvězdičky (*).

Shoda s nulou nebo více časy: *

Kvantifikátor * odpovídá předchozímu prvku nulakrát nebo vícekrát. Je to ekvivalent kvantifikátoru {0,} . * je greedy kvantifikátor, jehož opožděný ekvivalent je *?.

Následující příklad znázorňuje tento regulární výraz. Pět z devíti číslic ve vstupním řetězci odpovídá vzoru a čtyř (95, 929, 9219a 9919) ne.

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.

Vzor regulárního výrazu je definován, jak je znázorněno v následující tabulce:

Vzor Popis
\b Určuje, že shoda musí začínat na hranici slova.
91* Odpovídá nule nebo více znaků následovaným nulou 9 nebo více 1 znaky.
9* Odpovídá nule nebo více 9 znaků.
\b Určuje, že shoda musí končit na hranici slova.

Shoda jednou nebo vícekrát: +

Kvantifikátor + odpovídá předchozímu prvku jednou nebo vícekrát. Je to ekvivalent .{1,} + je greedy kvantifikátor, jehož opožděný ekvivalent je +?.

Například regulární výraz \ban+\w*?\b se pokusí shodovat celá slova, která začínají písmenem a následovaným jednou nebo více instancemi písmena n. Následující příklad znázorňuje tento regulární výraz. Regulární výraz odpovídá slovům an, annual, announcement, a antique, a správně se neshoduje autumn a 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.

Vzor regulárního výrazu je definován, jak je znázorněno v následující tabulce:

Vzor Popis
\b Začne na hranici slova.
an+ a Odpovídá jednomu nebo více n znakům.
\w*? Odpovídá znaku slova nula nebo vícekrát, ale co nejméněkrát.
\b Skončí na hranici slova.

Shoda s nulou nebo jednou: ?

Kvantifikátor ? odpovídá předchozímu prvku nula nebo jednou. Je to ekvivalent .{0,1} ? je greedy kvantifikátor, jehož opožděný ekvivalent je ??.

Regulární výraz \ban?\b se například pokusí shodovat celá slova, která začínají písmenem a následovaným nulou nebo jednou instancí písmena n. Jinými slovy, snaží se spárovat slova a a an. Následující příklad znázorňuje tento regulární výraz:

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.

Vzor regulárního výrazu je definován, jak je znázorněno v následující tabulce:

Vzor Popis
\b Začne na hranici slova.
an? Odpovídá tomuto znaku a , za nímž následuje nula nebo jeden n znak.
\b Skončí na hranici slova.

Přesně n Krát odpovídá: {n}

N {}kvantifikátor odpovídá předchozímu prvku přesně nkrát, kde n je jakékoli celé číslo. {n je kvantifikátor greedy, jehož opožděný ekvivalent je{ n}?.}

Regulární výraz \b\d+\,\d{3}\b se například pokusí shodovat s hranicí slova následovanou jednou nebo více desetinnými číslicemi následovanými třemi desetinnými číslicemi následovanými hranicí slova. Následující příklad znázorňuje tento regulární výraz:

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.

Vzor regulárního výrazu je definován, jak je znázorněno v následující tabulce:

Vzor Popis
\b Začne na hranici slova.
\d+ Odpovídá jedné nebo více desítkových číslic.
\, Odpovídá znaku čárky.
\d{3} Odpovídá třem desetinným číslicům.
\b Skončí na hranici slova.

Porovná alespoň nkrát: {n,}

N {,}kvantifikátor odpovídá předchozímu prvku alespoň nkrát, kde n je jakékoli celé číslo. {n je kvantifikátor greedy, jehož opožděný ekvivalent je{ n,}?.,}

Regulární výraz \b\d{2,}\b\D+ se například pokusí shodovat s hranicí slova následovanou alespoň dvěma číslicemi, za kterými následuje hranice slova a neciferný znak. Následující příklad znázorňuje tento regulární výraz. Regulární výraz neodpovídá frázi "7 days" , protože obsahuje pouze jednu desetinnou číslici, ale úspěšně odpovídá frázím "10 weeks" a "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.

Vzor regulárního výrazu je definován, jak je znázorněno v následující tabulce:

Vzor Popis
\b Začne na hranici slova.
\d{2,} Odpovídá alespoň dvěma desetinným číslicemi.
\b Odpovídá hranici slova.
\D+ Odpovídá alespoň jedné ne desetinné číslici.

Shoda mezi n a m časy: {n,m}

Kvantifikátor {n,m} odpovídá předchozímu prvku alespoň nkrát, ale ne více než m krát, kde n a m jsou celá čísla. {n,m} je kvantifikátor greedy, jehož opožděný ekvivalent je{ n,m.}?

V následujícím příkladu se regulární výraz (00\s){2,4} pokusí shodovat mezi dvěma a čtyřmi výskyty dvou nulových číslic následovaných mezerou. Poslední část vstupního řetězce obsahuje tento vzor pětkrát, nikoli maximálně čtyři. Pouze počáteční část tohoto podřetětěce (až do mezery a páté dvojice nul) však odpovídá vzoru regulárního výrazu.

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.

Shoda s nulovou nebo více časy (opožděná shoda): *?

Kvantifikátor *? odpovídá předchozímu prvku nula nebo vícekrát, ale co nejméněkrát. Je to opožděný protějšek kvantifikátoru *greedy .

V následujícím příkladu regulární výraz \b\w*?oo\w*?\b odpovídá všem slovem, která obsahují řetězec 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.

Vzor regulárního výrazu je definován, jak je znázorněno v následující tabulce:

Vzor Popis
\b Začne na hranici slova.
\w*? Odpovídá nule nebo více znaků slova, ale co nejvíce znaků.
oo Odpovídá řetězci oo.
\w*? Odpovídá nule nebo více znaků slova, ale co nejvíce znaků.
\b Končí na hranici slova.

Shoda jednou nebo vícekrát (opožděná shoda): +?

Kvantifikátor +? odpovídá předchozímu prvku jednou nebo vícekrát, ale co nejméněkrát. Je to opožděný protějšek kvantifikátoru +greedy .

Regulární výraz \b\w+?\b například odpovídá jednomu nebo více znakům odděleným hranicemi slova. Následující příklad znázorňuje tento regulární výraz:

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.

Shoda s nulou nebo jednou (opožděná shoda): ??

Kvantifikátor ?? odpovídá předchozímu prvku nula nebo jednou, ale co nejvícekrát. Je to opožděný protějšek kvantifikátoru ?greedy .

Například regulární výraz ^\s*(System.)??Console.Write(Line)??\(?? se pokusí shodovat s řetězci Console.Write nebo Console.WriteLine. Řetězec může obsahovat System. také před Consolea za ním může následovat levá závorka. Řetězec musí být na začátku řádku, i když může předcházet prázdným znakem. Následující příklad znázorňuje tento regulární výraz:

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.

Vzor regulárního výrazu je definován, jak je znázorněno v následující tabulce:

Vzor Popis
^ Odpovídá začátku vstupního datového proudu.
\s* Odpovídá nule nebo více prázdných znaků.
(System.)?? Odpovídá nule nebo jednomu výskytu řetězce System..
Console.Write Odpovídá řetězci Console.Write.
(Line)?? Odpovídá nule nebo jednomu výskytu řetězce Line.
\(?? Odpovídá nule nebo jednomu výskytu levé závorky.

Přesně n krát (opožděná shoda): {n}?

N {}? kvantifikátor přesně odpovídá předchozímu prvku, n kde n je libovolné celé číslo. Je to opožděný protějšek kvantifikátoru {greedy n}.

V následujícím příkladu se regulární výraz \b(\w{3,}?\.){2}?\w{3,}?\b používá k identifikaci webové adresy. Výraz se shoduje www.microsoft.com , msdn.microsoft.com ale neodpovídá mywebsite nebo 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.

Vzor regulárního výrazu je definován, jak je znázorněno v následující tabulce:

Vzor Popis
\b Začne na hranici slova.
(\w{3,}?\.) Odpovídá alespoň třem znakům slova, ale co nejvíce znaků, za kterými následuje tečka nebo tečka. Tento model je první zachytáváním skupiny.
(\w{3,}?\.){2}? Odpovídá vzoru v první skupině dvakrát, ale co nejméněkrát.
\b Ukončete shodu na hranici slova.

Odpovídá alespoň nkrát (opožděná shoda): {n,}?

N {,}?kvantifikátor odpovídá předchozímu prvku alespoň n jednou, kde n je jakékoli celé číslo, ale co nejvícekrát. Je to opožděný protějšek kvantifikátoru {greedy n,}.

Obrázek najdete v příkladu {n}? kvantifikátoru v předchozí části. Regulární výraz v tomto příkladu {používá kvantifikátor n,} ke shodě s řetězcem, který má aspoň tři znaky následované tečkou.

Shoda mezi n a m times (opožděná shoda): {n,m}?

Kvantifikátor {n,m}? odpovídá předchozímu prvku mezi n a m časy, kde n a m jsou celá čísla, ale co nejméněkrát. Je to opožděný protějšek kvantifikátoru {greedy n,m}.

V následujícím příkladu regulární výraz \b[A-Z](\w*?\s*?){1,10}[.!?] odpovídá větám, které obsahují 1 až 10 slov. Odpovídá všem větám ve vstupním řetězci s výjimkou jedné věty, která obsahuje 18 slov.

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.

Vzor regulárního výrazu je definován, jak je znázorněno v následující tabulce:

Vzor Popis
\b Začne na hranici slova.
[A-Z] Odpovídá velkým písmenům od A do Z.
(\w*?\s*?) Odpovídá nule nebo několika znakům slova, za kterými následuje jedno nebo více prázdných znaků, ale co nejvícekrát. Tento model je první zachytáváním skupiny.
{1,10} Odpovídá předchozímu vzoru mezi 1 a 10krát.
[.!?] Odpovídá libovolnému z interpunkčních znaků ., !nebo ?.

Greedy a Lazy Kvantifikátory

Některé kvantifikátory mají dvě verze:

  • Greedy verze.

    Kvantifikátor greedy se snaží co nejvíce spárovat prvek.

  • Nesměšná (nebo opožděná) verze.

    Kvantifikátor, který není greedy, se snaží co nejvíce spárovat prvek. Kvantifikátor greedy můžete změnit na opožděný kvantifikátor přidáním .?

Představte si regulární výraz, který má extrahovat poslední čtyři číslice z řetězce čísel, jako je číslo platební karty. Verze regulárního výrazu, který používá * kvantifikátor greedy, je \b.*([0-9]{4})\b. Pokud ale řetězec obsahuje dvě čísla, bude tento regulární výraz odpovídat posledním čtyřmístným číslicům druhého čísla, jak ukazuje následující příklad:

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.

Regulární výraz neodpovídá prvnímu číslu, protože * kvantifikátor se snaží shodovat s předchozím prvkem tolikrát, kolikrát je to možné v celém řetězci, a proto najde shodu na konci řetězce.

Toto chování není požadované. Místo toho můžete pomocí opožděného kvantifikátoru *? extrahovat číslice z obou čísel, jak ukazuje následující příklad:

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.

Ve většině případů regulární výrazy s greedy a opožděnými kvantifikátory vrací stejné shody. Nejčastěji vrací různé výsledky, když se používají se zástupným znakem (.metacharacter), který odpovídá jakémukoli znaku.

Kvantifikátory a prázdné shody

Kvantifikátory *, +a {n,m} a jejich opožděné protějšky se nikdy neopakují po prázdné shodě, pokud byl nalezen minimální počet zachycení. Toto pravidlo zabraňuje kvantifikátorům v zadávání nekonečných smyček na prázdném dílčím výrazu, pokud je maximální počet možných zachycení skupin nekonečný nebo téměř nekonečný.

Následující kód například ukazuje výsledek volání Regex.Match metody se vzorem (a?)*regulárního výrazu , který odpovídá nule nebo jednomu a znaku nula nebo vícekrát. Jedna zachytávací skupina zachytí každou z nich a , String.Emptyale neexistuje žádná druhá prázdná shoda, protože první prázdná shoda způsobí, že kvantifikátor přestane opakovat.

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

Chcete-li zjistit praktický rozdíl mezi zachytáváním skupiny, která definuje minimální a maximální počet zachycení a jeden, který definuje pevný počet zachycení, zvažte vzory regulárních výrazů (a\1|(?(1)\1)){0,2} a (a\1|(?(1)\1)){2}. Oba regulární výrazy se skládají z jedné skupiny zachycení, která je definována v následující tabulce:

Vzor Popis
(a\1 Buď se shoduje a s hodnotou první zachycené skupiny ...
|(?(1) … nebo testuje, zda byla definována první zachycená skupina. Konstruktor (?(1) nedefinuje zachytávání skupiny.
\1)) Pokud existuje první zachycená skupina, odpovídá její hodnotě. Pokud skupina neexistuje, bude se skupina shodovat String.Empty.

První regulární výraz se pokusí tento vzor spárovat mezi nulou a dvěma krát; druhé, přesně dvakrát. Vzhledem k tomu, že první vzor dosáhne minimálního počtu zachycení s prvním zachycením String.Empty, nikdy se neopakuje, aby se pokusil shodovat a\1. Kvantifikátor {0,2} umožňuje pouze prázdné shody v poslední iteraci. Druhý regulární výraz se naopak shoduje a , protože se vyhodnotí a\1 podruhé. Minimální počet iterací 2 vynutí, aby se modul opakoval po prázdné shodě.

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.

Viz také