Kvantifikátory v regulárních výrazech
Kvantifikátory určují, kolik instancí znaku, skupiny nebo třídy znaků musí být přítomno ve vstupu, aby byla nalezena shoda. Následující tabulka uvádí kvantifikátory podporované v .NET:
Kvantifikátor chamtivosti | Opožděný kvantifikátor | Description |
---|---|---|
* |
*? |
Odpovídá nule nebo vícekrát. |
+ |
+? |
Jednou nebo vícekrát odpovídá. |
? |
?? |
Odpovídá nule nebo jednou. |
{ N} |
{ N}? |
Odpovídá přesně n krát. |
{ N,} |
{ N,}? |
Odpovídá alespoň nkrát . |
{ N, M} |
{ N, M}? |
Shoduje se od n do m krát. |
n
Množství a m
jsou celočíselné konstanty. Kvantifikátory jsou obvykle chamtiví. Způsobí, že modul regulárních výrazů odpovídá co nejvíce výskytům konkrétních vzorů. Připojení znaku ?
k kvantifikátoru způsobí, že bude opožděný. To způsobí, že modul regulárních výrazů odpovídá co nejméně výskytům. Úplný popis rozdílu mezi chamtivými 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řování kvantifikátorů, jako je například 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 Vrácení zpět.
Kvantifikátory regulárních výrazů
Následující části obsahují seznam kvantifikátorů podporovaných regulárními výrazy .NET:
Poznámka
Pokud jsou znaky *, +, ?, {a } nalezeny ve vzorech regulárních výrazů, modul regulárních výrazů je interpretuje jako kvantifikátory nebo součást konstruktorů kvantifikátoru, pokud nejsou zahrnuty do třídy znaků. Pokud chcete tyto znaky interpretovat jako literály mimo třídu znaků, musíte před nimi utéct zpětným lomítkem. Například řetězec \*
ve vzoru regulárního výrazu je interpretován jako literální znak hvězdičky ("*").
Shoda nula nebo vícekrát: *
Kvantifikátor *
odpovídá předchozímu prvku nula nebo vícekrát. Je to ekvivalent kvantifikátoru {0,}
. *
je chamtivý kvantifikátor, jehož líný ekvivalent je *?
.
Následující příklad znázorňuje tento regulární výraz. Pět z devíti skupin číslic ve vstupním řetězci odpovídá vzoru a čtyři (95
, 929
9219
, a 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 definovaný tak, jak je znázorněno v následující tabulce:
Vzor | Description |
---|---|
\b |
Určuje, že shoda musí začínat na hranici slova. |
91* |
Odpovídá znaky 9 následované nulou 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 +
jednou nebo vícekrát odpovídá předchozímu prvku. Je to ekvivalent k {1,}
. +
je chamtivý kvantifikátor, jehož líný ekvivalent je +?
.
Regulární výraz \ban+\w*?\b
se například pokusí shodovat celá slova, která začínají písmenem a
, za kterým následuje jeden nebo více výskytů 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 s 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 definovaný tak, jak je znázorněno v následující tabulce:
Vzor | Description |
---|---|
\b |
Začne na hranici slova. |
an+ |
Odpovídá znaku následovaného a jedním nebo více n znaky. |
\w*? |
Porovná znak slova nula nebo vícekrát, ale co nejméněkrát. |
\b |
Skončí na hranici slova. |
Shoda nula nebo jednorázově: ?
Kvantifikátor ?
odpovídá předchozímu prvku nula nebo jednorázově. Je to ekvivalent k {0,1}
. ?
je chamtivý kvantifikátor, jehož líný ekvivalent je ??
.
Regulární výraz \ban?\b
se například pokusí shodovat celá slova, která začínají písmenem a
, za kterým následuje nula nebo jedna instance písmena n
. Jinými slovy se pokusí shodovat 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 definovaný tak, jak je znázorněno v následující tabulce:
Vzor | Description |
---|---|
\b |
Začne na hranici slova. |
an? |
Odpovídá hodnotě a následované nulou nebo jedním n znakem. |
\b |
Skončí na hranici slova. |
Přesně n krát: {n}
Kvantifikátor {
n}
odpovídá předchozímu prvku přesně n krát, kde n je libovolné celé číslo. {
n}
je chamtivý kvantifikátor, jehož opožděný ekvivalent je {
n}?
.
Regulární výraz \b\d+\,\d{3}\b
se například pokusí spárovat hranici slova následovanou jednou nebo více desetinnými číslicemi následovanými třemi desetinnými číslicemi následovanými ohraničením 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 definovaný tak, jak je znázorněno v následující tabulce:
Vzor | Description |
---|---|
\b |
Začne na hranici slova. |
\d+ |
Odpovídá jedné nebo více desetinných číslic. |
\, |
Odpovídá znaku čárky. |
\d{3} |
Odpovídá třem desetinným číslicům. |
\b |
Skončí na hranici slova. |
Shoda alespoň nkrát: {n,}
Kvantifikátor {
n,}
odpovídá předchozímu prvku alespoň nkrát , kde n je libovolné celé číslo. {
n,}
je chamtivý kvantifikátor, jehož opožděný ekvivalent je {
n,}?
.
Například regulární výraz \b\d{2,}\b\D+
se pokusí spárovat hranici slova následovanou alespoň dvěma číslicemi následovanými ohraničením slova a neciferným znakem. 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 definovaný tak, jak je znázorněno v následující tabulce:
Vzor | Description |
---|---|
\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é neciferné čí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 chamtivý kvantifikátor, jehož lí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 zahrnuje tento vzor pětkrát, nikoli maximálně čtyřikrát. Vzor regulárního výrazu však odpovídá pouze počáteční část tohoto podřetěžce (až mezera a pátá dvojice nul).
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 nula nebo vícekrát (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 líný protějšek chamtivého kvantifikátoru *
.
V následujícím příkladu regulární výraz \b\w*?oo\w*?\b
odpovídá všem slovem obsahujícím ř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 definovaný tak, jak je znázorněno v následující tabulce:
Vzor | Description |
---|---|
\b |
Začne na hranici slova. |
\w*? |
Odpovídá nule nebo více znaků slova, ale co nejméně znaků. |
oo |
Odpovídá řetězci oo . |
\w*? |
Odpovídá nule nebo více znaků slova, ale co nejméně znaků. |
\b |
Konec 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 líný protějšek chamtivého kvantifikátoru +
.
Například regulární výraz \b\w+?\b
odpovídá jednomu nebo více znakům odděleným hranicemi slov. 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 nula nebo jednorázová (opožděná shoda): ??
Kvantifikátor ??
odpovídá předchozímu prvku nula nebo jednorázově, ale co nejméněkrát. Je to líný protějšek chamtivého kvantifikátoru ?
.
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 Console
a za ním může následovat levá závorka. Řetězec musí být na začátku řádku, i když mu může předcházet prázdné znaky. 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 definovaný tak, jak je znázorněno v následující tabulce:
Vzor | Description |
---|---|
^ |
Odpovídá začátku vstupního streamu. |
\s* |
Odpovídá nule nebo více prázdných znaků. |
(System.)?? |
Odpovídá nulovému nebo jednomu výskytu řetězce System. . |
Console.Write |
Odpovídá řetězci Console.Write . |
(Line)?? |
Odpovídá nulovému nebo jednomu výskytu řetězce Line . |
\(?? |
Odpovídá nulovému nebo jednomu výskytu levých závorek. |
Přesně n krát (opožděná shoda): {n}?
Kvantifikátor {
n}?
přesně odpovídá předchozímu prvku n
times, kde n je libovolné celé číslo. Je to líný protějšek chamtivého kvantifikátoru {
n}
.
V následujícím příkladu se k identifikaci webové adresy používá regulární výraz \b(\w{3,}?\.){2}?\w{3,}?\b
. Výraz odpovídá www.microsoft.com
a 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 definovaný tak, jak je znázorněno v následující tabulce:
Vzor | Description |
---|---|
\b |
Začne na hranici slova. |
(\w{3,}?\.) |
Odpovídá alespoň třem znakům slova, ale co nejméně znaků, za kterými následuje tečka nebo tečka. Tento model je první zachytávání skupiny. |
(\w{3,}?\.){2}? |
Porovná vzor 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,}?
Kvantifikátor {
n,}?
odpovídá předchozímu prvku alespoň n
krát, kde n je libovolné celé číslo, ale co nejméněkrát. Je to líný protějšek chamtivého kvantifikátoru {
n,}
.
Obrázek najdete v příkladu {
kvantifikátoru n}?
v předchozí části. Regulární výraz v tomto příkladu {
používá kvantifikátor n,}
, aby odpovídal řetězci, který má alespoň tři znaky následované tečkou.
Shoda mezi n a m časy (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 líný protějšek chamtivého kvantifikátoru {
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 definovaný tak, jak je znázorněno v následující tabulce:
Vzor | Description |
---|---|
\b |
Začne na hranici slova. |
[A-Z] |
Odpovídá velkým písmenům od A do Z. |
(\w*?\s*?) |
Porovná nula nebo více znaků slova následovaných jedním nebo více prázdnými znaky, ale co nejméněkrát. Tento model je první zachytávání skupiny. |
{1,10} |
Odpovídá předchozímu vzoru 1 až 10krát. |
[.!?] |
Odpovídá libovolnému interpunkčnímu znaménu . , ! nebo ? . |
Chamtivé a opožděné kvantifikátory
Některé kvantifikátory mají dvě verze:
Chamtivá verze.
Chamtivý kvantifikátor se snaží co nejvícekrát shodovat s prvkem.
Nechtivá (nebo líná) verze.
Nekytivý kvantifikátor se snaží co nejméněkrát shodovat s prvkem. Chamtivý kvantifikátor 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, například čísla platební karty. Verze regulárního výrazu, který používá *
kvantifikátor chamtivosti, je \b.*([0-9]{4})\b
. Pokud ale řetězec obsahuje dvě čísla, tento regulární výraz odpovídá pouze posledním čtyřem čí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ží co nejvícekrát spárovat předchozí prvek v celém řetězci, a tak 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ů vrátí regulární výrazy s chamtivými a opožděnými kvantifikátory stejné shody. Nejčastěji vrací různé výsledky, když se použijí se zástupným znakem (.
), který odpovídá jakémukoli znaku.
Kvantifikátory a prázdné shody
Kvantifikátory *
, +
a {
n,
m}
a jejich lí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 u prázdných dílčích výrazů, pokud je maximální počet možných zachycení skupin nekonečný nebo téměř nekonečný.
Například následující kód zobrazuje 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ává jednotlivé a
a String.Empty, ale neexistuje žádná druhá prázdná shoda, protože první prázdná shoda způsobí, že se 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
Pokud chcete zjistit praktický rozdíl mezi skupinou zachycení, která definuje minimální a maximální počet zachycení, a skupinou, 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é zachytávkové skupiny, která je definována v následující tabulce:
Vzor | Description |
---|---|
(a\1 |
Buď odpovídá a hodnotě první zachycené skupiny ... |
|(?(1) |
… nebo testuje, jestli byla definována první zachycená skupina. Konstruktor (?(1) nedefinuje zachytávání skupiny. |
\1)) |
Pokud existuje první zachycená skupina, shodujte její hodnotu. Pokud skupina neexistuje, bude odpovídat String.Emptyskupině . |
První regulární výraz se pokusí shodovat tento vzor mezi nulou a dvakrát; druhý, přesně dvakrát. Vzhledem k tomu, že první vzor dosáhne minimálního počtu zachycení s prvním zachytávání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. Naproti tomu druhý regulární výraz se shoduje a
, protože se vyhodnotí a\1
podruhé. Minimální počet iterací 2 vynutí opakování modulu 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.