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 Consolede , 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.

Consulte também