Quantificadores em expressões regulares
Os quantificadores especificam quantas instâncias de um caractere, grupo ou classe de caractere devem estar presentes na entrada para que uma correspondência seja encontrada. A tabela a seguir lista os quantificadores suportados pelo .NET:
Quantificador ganancioso | Quantificador preguiçoso | Description |
---|---|---|
* |
*? |
Corresponde a zero ou mais vezes. |
+ |
+? |
Corresponde uma ou mais vezes. |
? |
?? |
Corresponde a zero ou uma vez. |
{ n } |
{ n }? |
Corresponde exatamente n vezes. |
{ n ,} |
{ n ,}? |
Corresponde pelo menos n vezes. |
{ n , O } |
{ n , O }? |
Jogos de n a m vezes. |
As quantidades n
e m
são constantes inteiras. Normalmente, os quantificadores são gananciosos. Eles fazem com que o mecanismo de expressão regular corresponda ao maior número possível de ocorrências de padrões específicos. Anexar o ?
personagem a um quantificador torna-o preguiçoso. Isso faz com que o mecanismo de expressão regular corresponda ao menor número possível de ocorrências. Para obter uma descrição completa da diferença entre quantificadores gananciosos e preguiçosos, consulte a seção Quantificadores gananciosos e preguiçosos mais adiante neste artigo.
Importante
Os quantificadores de aninhamento, como o padrão (a*)*
de expressão regular, podem aumentar o número de comparações que o mecanismo de expressão regular deve executar. O número de comparações pode aumentar como uma função exponencial do número de caracteres na cadeia de entrada. Para obter mais informações sobre esse comportamento e suas soluções alternativas, consulte Backtracking.
Quantificadores de Expressão Regular
As seções a seguir listam os quantificadores suportados pelas expressões regulares do .NET:
Nota
Se os caracteres *, +, ?, { e } forem encontrados em um padrão de expressão regular, o mecanismo de expressão regular os interpretará como quantificadores ou parte de construções quantificadoras, a menos que sejam incluídos em uma classe de caracteres. Para interpretá-los como caracteres literais fora de uma classe de caracteres, você deve escapar deles precedendo-os com uma barra invertida. Por exemplo, a cadeia de caracteres \*
em um padrão de expressão regular é interpretada como um caractere de asterisco literal ("*").
Corresponder zero ou mais vezes: *
O *
quantificador corresponde ao elemento anterior zero ou mais vezes. É equivalente ao {0,}
quantificador. *
é um quantificador ganancioso cujo equivalente preguiçoso é *?
.
O exemplo a seguir ilustra essa expressão regular. Cinco dos nove grupos de dígitos na cadeia de caracteres de entrada correspondem ao padrão e quatro (95
, 929
, 9219
, e 9919
) não.
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.
O padrão de expressão regular é definido conforme mostrado na tabela a seguir:
Padrão | Description |
---|---|
\b |
Especifica que a correspondência deve começar em um limite de palavras. |
91* |
Corresponde a um 9 seguido por zero ou mais 1 caracteres. |
9* |
Corresponde a zero ou mais 9 caracteres. |
\b |
Especifica que a correspondência deve terminar em um limite de palavras. |
Corresponder uma ou mais vezes: +
O +
quantificador corresponde ao elemento anterior uma ou mais vezes. É equivalente a {1,}
. +
é um quantificador ganancioso cujo equivalente preguiçoso é +?
.
Por exemplo, a expressão \ban+\w*?\b
regular tenta corresponder palavras inteiras que começam com a letra a
seguida por uma ou mais ocorrências da letra n
. O exemplo a seguir ilustra essa expressão regular. A expressão regular corresponde às palavras an
, annual
, announcement
, e antique
, e não corresponde corretamente e autumn
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.
O padrão de expressão regular é definido conforme mostrado na tabela a seguir:
Padrão | Description |
---|---|
\b |
Comece com um limite de palavras. |
an+ |
Corresponde a um a seguido por um ou mais n caracteres. |
\w*? |
Corresponde a um caractere de palavra zero ou mais vezes, mas o menor número de vezes possível. |
\b |
Termine com um limite de palavras. |
Corresponder Zero ou Uma Vez: ?
O ?
quantificador corresponde ao elemento anterior zero ou uma vez. É equivalente a {0,1}
. ?
é um quantificador ganancioso cujo equivalente preguiçoso é ??
.
Por exemplo, a expressão \ban?\b
regular tenta corresponder palavras inteiras que começam com a letra a
seguida de zero ou uma ocorrência da letra n
. Por outras palavras, tenta fazer corresponder as palavras a
e an
. O exemplo a seguir ilustra essa expressão regular:
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.
O padrão de expressão regular é definido conforme mostrado na tabela a seguir:
Padrão | Description |
---|---|
\b |
Comece com um limite de palavras. |
an? |
Corresponde a um a seguido de zero ou um n caractere. |
\b |
Termine com um limite de palavras. |
Corresponder exatamente n vezes: {n}
O {
quantificador n}
corresponde ao elemento anterior exatamente n vezes, onde n é qualquer inteiro. {
n é um quantificador ganancioso cujo equivalente preguiçoso é{
n}?
.}
Por exemplo, a expressão \b\d+\,\d{3}\b
regular tenta corresponder a um limite de palavra seguido por um ou mais dígitos decimais seguidos por três dígitos decimais seguidos por um limite de palavra. O exemplo a seguir ilustra essa expressão regular:
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.
O padrão de expressão regular é definido conforme mostrado na tabela a seguir:
Padrão | Description |
---|---|
\b |
Comece com um limite de palavras. |
\d+ |
Corresponde a um ou mais dígitos decimais. |
\, |
Corresponde a um caractere de vírgula. |
\d{3} |
Corresponde a três dígitos decimais. |
\b |
Termine com um limite de palavras. |
Corresponder pelo menos n vezes: {n,}
O {
quantificador n,}
corresponde ao elemento anterior pelo menos n vezes, onde n é qualquer inteiro. {
n é um quantificador ganancioso cujo equivalente preguiçoso é{
n,}?
.,}
Por exemplo, a expressão \b\d{2,}\b\D+
regular tenta corresponder a um limite de palavra seguido por pelo menos dois dígitos seguidos por um limite de palavra e um caractere sem dígitos. O exemplo a seguir ilustra essa expressão regular. A expressão regular não corresponde à frase "7 days"
porque contém apenas um dígito decimal, mas corresponde com êxito às frases "10 weeks"
e "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.
O padrão de expressão regular é definido conforme mostrado na tabela a seguir:
Padrão | Description |
---|---|
\b |
Comece com um limite de palavras. |
\d{2,} |
Corresponde a pelo menos dois dígitos decimais. |
\b |
Corresponde a um limite de palavras. |
\D+ |
Corresponde a pelo menos um dígito não decimal. |
Correspondência entre n e m Tempos: {n,m}
O {
quantificador n,
m}
corresponde ao elemento precedente pelo menos n vezes, mas não mais do que m vezes, onde n e m são inteiros. {
n,
m}
é um quantificador ganancioso cujo equivalente preguiçoso é{
n,
m.}?
No exemplo a seguir, a expressão (00\s){2,4}
regular tenta corresponder entre duas e quatro ocorrências de dois dígitos zero seguidos por um espaço. A parte final da cadeia de caracteres de entrada inclui esse padrão cinco vezes, em vez do máximo de quatro. No entanto, apenas a parte inicial desta substring (até o espaço e o quinto par de zeros) corresponde ao padrão de expressão regular.
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.
Match Zero ou Mais Vezes (Prezy Match): *?
O *?
quantificador corresponde ao elemento anterior zero ou mais vezes, mas o menor número de vezes possível. É a contrapartida preguiçosa do quantificador ganancioso *
.
No exemplo a seguir, a expressão \b\w*?oo\w*?\b
regular corresponde a todas as palavras que contêm a cadeia de caracteres 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.
O padrão de expressão regular é definido conforme mostrado na tabela a seguir:
Padrão | Description |
---|---|
\b |
Comece com um limite de palavras. |
\w*? |
Corresponde a zero ou mais caracteres de palavras, mas ao menor número possível de caracteres. |
oo |
Corresponde à cadeia de caracteres oo . |
\w*? |
Corresponde a zero ou mais caracteres de palavras, mas ao menor número possível de caracteres. |
\b |
Termine com um limite de palavras. |
Corresponder uma ou mais vezes (jogo preguiçoso): +?
O +?
quantificador corresponde ao elemento anterior uma ou mais vezes, mas o menor número de vezes possível. É a contrapartida preguiçosa do quantificador ganancioso +
.
Por exemplo, a expressão \b\w+?\b
regular corresponde a um ou mais caracteres separados por limites de palavras. O exemplo a seguir ilustra essa expressão regular:
string pattern = @"\b\w+?\b";
string input = "Aa Bb Cc Dd Ee Ff";
foreach (Match match in Regex.Matches(input, pattern))
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);
// The example displays the following output:
// 'Aa' found at position 0.
// 'Bb' found at position 3.
// 'Cc' found at position 6.
// 'Dd' found at position 9.
// 'Ee' found at position 12.
// 'Ff' found at position 15.
Dim pattern As String = "\b\w+?\b"
Dim input As String = "Aa Bb Cc Dd Ee Ff"
For Each match As Match In Regex.Matches(input, pattern)
Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
Next
' The example displays the following output:
' 'Aa' found at position 0.
' 'Bb' found at position 3.
' 'Cc' found at position 6.
' 'Dd' found at position 9.
' 'Ee' found at position 12.
' 'Ff' found at position 15.
Match Zero ou One Time (jogo preguiçoso): ??
O ??
quantificador corresponde ao elemento anterior zero ou uma vez, mas o menor número de vezes possível. É a contrapartida preguiçosa do quantificador ganancioso ?
.
Por exemplo, a expressão ^\s*(System.)??Console.Write(Line)??\(??
regular tenta corresponder às cadeias de Console.Write
caracteres ou Console.WriteLine
. A cadeia de caracteres também pode incluir System.
antes Console
de , e pode ser seguida por um parêntese de abertura. A cadeia de caracteres deve estar no início de uma linha, embora possa ser precedida por espaço em branco. O exemplo a seguir ilustra essa expressão regular:
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.
O padrão de expressão regular é definido conforme mostrado na tabela a seguir:
Padrão | Description |
---|---|
^ |
Corresponde ao início do fluxo de entrada. |
\s* |
Corresponde a zero ou mais caracteres de espaço em branco. |
(System.)?? |
Corresponde a zero ou uma ocorrência da cadeia de caracteres System. . |
Console.Write |
Corresponde à cadeia de caracteres Console.Write . |
(Line)?? |
Corresponde a zero ou uma ocorrência da cadeia de caracteres Line . |
\(?? |
Corresponde a zero ou uma ocorrência do parêntese de abertura. |
Match Exactly n Times (Jogo Preguiçoso): {n}?
O {
quantificador n}?
corresponde ao elemento anterior exatamente n
vezes, onde n é qualquer inteiro. É a contrapartida preguiçosa do quantificador {
ganancioso n}
.
No exemplo a seguir, a expressão \b(\w{3,}?\.){2}?\w{3,}?\b
regular é usada para identificar um endereço de site. A expressão corresponde e www.microsoft.com
msdn.microsoft.com
mas não corresponde mywebsite
ou 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.
O padrão de expressão regular é definido conforme mostrado na tabela a seguir:
Padrão | Description |
---|---|
\b |
Comece com um limite de palavras. |
(\w{3,}?\.) |
Corresponde a pelo menos três caracteres de palavra, mas o menor número possível de caracteres, seguido por um caractere de ponto ou ponto. Este padrão é o primeiro grupo de captura. |
(\w{3,}?\.){2}? |
Corresponde ao padrão no primeiro grupo duas vezes, mas o menor número de vezes possível. |
\b |
Termine a partida com um limite de palavras. |
Match pelo menos n vezes (Lazy Match): {n,}?
O {
quantificador n,}?
corresponde ao elemento anterior pelo menos n
vezes, onde n é qualquer inteiro, mas o menor número de vezes possível. É a contrapartida preguiçosa do quantificador {
ganancioso n,}
.
Veja o exemplo para o {
quantificador n}?
na seção anterior para uma ilustração. A expressão regular nesse exemplo usa o {
quantificador n,}
para corresponder a uma cadeia de caracteres que tem pelo menos três caracteres seguidos por um ponto.
Match Between n and m Times (Lazy Match): {n,m}?
O {
quantificador n,
m}?
corresponde ao elemento precedente entre n
e m
tempos, onde n e m são inteiros, mas o menor número de vezes possível. É a contrapartida preguiçosa do ganancioso quantificador {
n,
m.}
No exemplo a seguir, a expressão \b[A-Z](\w*?\s*?){1,10}[.!?]
regular corresponde a frases que contêm entre 1 e 10 palavras. Ele corresponde a todas as frases na cadeia de entrada, exceto uma frase que contém 18 palavras.
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.
O padrão de expressão regular é definido conforme mostrado na tabela a seguir:
Padrão | Description |
---|---|
\b |
Comece com um limite de palavras. |
[A-Z] |
Corresponde a um caractere maiúsculo de A a Z. |
(\w*?\s*?) |
Corresponde a zero ou mais caracteres de palavras, seguidos por um ou mais caracteres de espaço em branco, mas o menor número de vezes possível. Este padrão é o primeiro grupo de captura. |
{1,10} |
Corresponde ao padrão anterior entre 1 e 10 vezes. |
[.!?] |
Corresponde a qualquer um dos caracteres . de pontuação , ! ou ? . |
Quantifiers gananciosos e preguiçosos
Alguns quantificadores têm duas versões:
Uma versão gananciosa.
Um quantificador ganancioso tenta corresponder a um elemento o maior número de vezes possível.
Uma versão não gananciosa (ou preguiçosa).
Um quantificador não ganancioso tenta corresponder a um elemento o menor número de vezes possível. Você pode transformar um quantificador ganancioso em um quantificador preguiçoso adicionando um
?
.
Considere uma expressão regular destinada a extrair os últimos quatro dígitos de uma cadeia de números, como um número de cartão de crédito. A versão da expressão regular que usa o *
quantificador ganancioso é \b.*([0-9]{4})\b
. No entanto, se uma cadeia de caracteres contiver dois números, essa expressão regular corresponderá apenas aos últimos quatro dígitos do segundo número, como mostra o exemplo a seguir:
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.
A expressão regular não consegue corresponder ao primeiro número porque o *
quantificador tenta corresponder ao elemento anterior tantas vezes quanto possível em toda a cadeia de caracteres e, portanto, encontra sua correspondência no final da cadeia de caracteres.
Esse comportamento não é o desejado. Em vez disso, você pode usar o *?
quantificador preguiçoso para extrair dígitos de ambos os números, como mostra o exemplo a seguir:
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.
Na maioria dos casos, expressões regulares com quantificadores gananciosos e preguiçosos retornam as mesmas correspondências. Eles geralmente retornam resultados diferentes quando são usados com o metacaractere curinga (.
), que corresponde a qualquer caractere.
Quantificadores e correspondências vazias
Os quantificadores *
, +
, e{
n,
m}
e seus homólogos preguiçosos nunca se repetem após uma partida vazia quando o número mínimo de capturas foi encontrado. Esta regra impede que os quantificadores entrem loops infinitos em correspondências de subexpressões vazias quando o número máximo de capturas de grupo possíveis é infinito ou quase infinito.
Por exemplo, o código a seguir mostra o resultado de uma chamada para o Regex.Match método com o padrão (a?)*
de expressão regular , que corresponde a zero ou um a
caractere zero ou mais vezes. O grupo de captura única captura cada a
um e String.Empty, mas não há uma segunda correspondência vazia porque a primeira correspondência vazia faz com que o quantificador pare de se repetir.
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
Para ver a diferença prática entre um grupo de captura que define um número mínimo e máximo de capturas e um que define um número fixo de capturas, considere os padrões (a\1|(?(1)\1)){0,2}
de expressão regular e (a\1|(?(1)\1)){2}
. Ambas as expressões regulares consistem em um único grupo de captura, que é definido na tabela a seguir:
Padrão | Description |
---|---|
(a\1 |
Ou corresponde a juntamente com o valor do primeiro grupo capturado ... |
|(?(1) |
… ou testa se o primeiro grupo capturado foi definido. A (?(1) construção não define um grupo de captura. |
\1)) |
Se o primeiro grupo capturado existir, corresponda ao seu valor. Se o grupo não existir, o grupo corresponderá String.Emptyao . |
A primeira expressão regular tenta corresponder a este padrão entre zero e duas vezes; a segunda, exatamente duas vezes. Como o primeiro padrão atinge seu número mínimo de capturas com sua primeira captura de String.Empty, ele nunca se repete para tentar corresponder a\1
. O {0,2}
quantificador permite apenas correspondências vazias na última iteração. Em contraste, a segunda expressão regular corresponde a
porque avalia a\1
uma segunda vez. O número mínimo de iterações, 2, força o motor a repetir após uma partida vazia.
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.