Partilhar via


Retrocedendo

Backtracking ocorre quando um padrão de expressão regular contém opcional quantificadores ou alternação constrói, e o mecanismo de expressão regular retorna ao estado anterior salvo para continuar sua pesquisa por uma correspondência. Backtracking é fundamental para a alimentação de expressões regulares; Ele possibilita que expressões poderosa e flexível e corresponder os padrões muito complexas. Ao mesmo tempo, essa energia é fornecida por um custo. Backtracking geralmente é o único fator mais importante que afeta o desempenho do mecanismo de expressões regulares. Felizmente, o desenvolvedor tem controle sobre o comportamento do mecanismo de expressões regulares e como ele usa backtracking. Este tópico explica como backtracking funciona e como ele pode ser controlado.

Observação

Em geral, um mecanismo de automação não determinísticas finito (NFA), como o.Mecanismo de expressões regulares do NET Framework coloca a responsabilidade por criar expressões eficientes e rápido regulares de desenvolvedor.

Este tópico contém as seções a seguir:

  • Comparação de linear sem Backtracking

  • Backtracking com quantificadores opcionais ou alternação construções.

  • Backtracking com quantificadores aninhados de opcionais

  • Controlando o Backtracking

Comparação de linear sem Backtracking

Se um padrão de expressão regular tem não quantificadores opcionais ou construções de alternância, o mecanismo de expressão regular é executado no tempo linear. Isto é, após o mecanismo de expressão regular corresponde ao primeiro elemento de linguagem no padrão com o texto na seqüência de entrada, ele tenta corresponder o próximo elemento de linguagem no padrão com o próximo caractere ou grupo de caracteres na seqüência de entrada. Isso continua até que a correspondência for bem-sucedida ou falha. Em ambos os casos, o mecanismo de expressão regular avança por um caractere por vez na seqüência de entrada.

O exemplo a seguir fornece uma ilustração. A expressão regular e{2}\w\b procura duas ocorrências da letra "e" seguido de qualquer caractere de palavra, seguido por um limite de palavra.

Imports System.Text.RegularExpressions

Module Example
   Public Sub Main()
      Dim input As String = "needing a reed"
      Dim pattern As String = "e{2}\w\b"
      For Each match As Match In Regex.Matches(input, pattern)
         Console.WriteLine("{0} found at position {1}", _
                           match.Value, match.Index)
      Next   
   End Sub
End Module
' The example displays the following output:
'       eed found at position 11
using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string input = "needing a reed";
      string pattern = @"e{2}\w\b";
      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:
//       eed found at position 11

Embora essa expressão regular inclui o quantificador {2}, ele é avaliado em uma maneira linear. O mecanismo de expressão regular não rastreamento inverso porque {2} é não um quantificador opcional; Especifica um número exato e não um número variável de vezes que a subexpressão anterior deve coincidir. Como resultado, o mecanismo de expressão regular tenta coincidir com o padrão de expressão regular com a seqüência de caracteres de entrada, como mostrado na tabela a seguir.

Operation

Posição padrão

Posição na seqüência

Resultado

1

e

a necessidade de um sensor (índice 0)

Nenhuma correspondência.

2

e

eeding um reed (índice 1)

Correspondência possível.

3

e {2}

eding um reed (índice 2)

Correspondência possível.

4

\w

Ding um reed (índice 3)

Correspondência possível.

5

\b

ING um reed (índice 4)

Falha da correspondência possível.

6

e

ING um reed (índice 5)

Nenhuma correspondência.

7

e

NG um reed (índice 6)

Nenhuma correspondência.

8

e

g um reed (índice 7)

Nenhuma correspondência.

9

e

um sensor (índice 8)

Nenhuma correspondência.

10

e

um sensor (índice 9)

Nenhuma correspondência.

11

e

Reed (índice 10)

Nenhuma correspondência.

12

e

Reed (índice 11)

Nenhuma correspondência

13

e

EED (12 de índice)

Correspondência possível.

14

e {2}

ED (índice 13)

Correspondência possível.

15

\w

d (índice de 14)

Correspondência possível.

16

\b

(índice 15)

Correspondência.

Se um padrão de expressão regular inclui nenhuma quantificadores opcionais ou construções de alternância, o número máximo de comparações necessárias para corresponder o padrão de expressão regular com a seqüência de caracteres de entrada é aproximadamente equivalente ao número de caracteres na seqüência de entrada. Em outras palavras, o mecanismo de expressão regular é executado no tempo linear se ela contiver nenhuma quantificadores opcionais ou a alternação construções.

Voltar ao topo

Backtracking com quantificadores opcionais ou alternação construções.

Quando uma expressão regular inclui quantificadores opcionais ou construções de alternância, a avaliação da seqüência de entrada não é mais linear. Padrão de correspondência com um mecanismo de NFA é orientada por elementos de linguagem na expressão regular e não pelos caracteres a ser correspondido a seqüência de caracteres de entrada. Portanto, o mecanismo de expressões regulares tenta corresponder totalmente o subexpressões opcionais ou alternativas. Quando ele avança para o próximo elemento de linguagem a subexpressão e a correspondência não for bem-sucedida, o mecanismo de expressão regular pode abandonar uma parte de sua correspondência correta e retornar para um estado salvo anteriormente no intuito de correspondência da expressão regular como um todo, com a seqüência de caracteres de entrada. Esse processo de retornar ao estado anterior salvo para localizar uma correspondência é conhecido como backtracking.

Por exemplo, considere o padrão de expressão regular .*(es), que coincide com os caracteres "es" e todos os caracteres que precedem. Como o exemplo a seguir mostra se a seqüência de caracteres de entrada for "serviços essenciais fornecidos por expressões regulares.", o padrão corresponde a seqüência inteira até e incluindo "es" em "expressões".

Imports System.Text.RegularExpressions

Module Example
   Public Sub Main()
      Dim input As String = "Essential services are provided by regular expressions."
      Dim pattern As String = ".*(es)" 
      Dim m As Match = Regex.Match(input, pattern, RegexOptions.IgnoreCase)
      If m.Success Then
         Console.WriteLine("'{0}' found at position {1}", _
                           m.Value, m.Index)
         Console.WriteLine("'es' found at position {0}", _
                           m.Groups(1).Index)                  
      End If     
   End Sub
End Module
'    'Essential services are provided by regular expres' found at position 0
'    'es' found at position 47
using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string input = "Essential services are provided by regular expressions.";
      string pattern = ".*(es)"; 
      Match m = Regex.Match(input, pattern, RegexOptions.IgnoreCase);
      if (m.Success) {
         Console.WriteLine("'{0}' found at position {1}", 
                           m.Value, m.Index);
         Console.WriteLine("'es' found at position {0}", 
                           m.Groups[1].Index);      
      } 
   }
}
//    'Essential services are provided by regular expres' found at position 0
//    'es' found at position 47

Para fazer isso, o mecanismo de expressão regular usa o backtracking da seguinte maneira:

  • Ela corresponde a .* (que corresponde a zero, um ou mais ocorrências de qualquer caractere) com a seqüência inteira de entrada.

  • Ele tenta corresponder a "e" no padrão de expressão regular. No entanto, a seqüência de caracteres de entrada não tem nenhum caracteres restantes disponíveis para corresponder.

  • Ele volta para a sua última correspondência correta, "serviços essenciais são fornecidos por expressões regulares" e tenta coincidir "e" com o ponto no final da sentença. A correspondência falha.

  • Ele continua refazer o caminho para um anterior correspondência bem-sucedida entre um caractere por vez até que a substring correspondida provisoriamente "serviços essenciais fornecidos por expr regular". Ele então compara o "e" no padrão para o segundo "e" em "expressões" e localiza uma correspondência.

  • Ele compara o "s" no padrão para "s" que segue o "e" correspondente caractere (o primeiro "s" em "expressões"). A correspondência for bem-sucedida.

Quando você usa o backtracking, correspondentes ao padrão de expressão regular com a seqüência de entrada, que é 55 caracteres, exige 67 operações de comparação. Curiosamente, se o padrão de expressão regular incluídas quantificador lazy.*?(es), exigiria a expressão regular de correspondência adicionais comparações. Nesse caso, em vez de ter que refazer o caminho do final da seqüência de caracteres "r" em "expressões", o mecanismo de expressão regular terá que refazer o caminho até o início da string para coincidir com "Es" e exigiria 113 comparações. Geralmente, se um padrão de expressão regular possui um quantificador opcional único ou uma construção de alternação único, o número de operações de comparação, necessárias para coincidir com o padrão é mais do dobro do número de caracteres na seqüência de entrada.

Voltar ao topo

Backtracking com quantificadores aninhados de opcionais

Se o padrão inclui um grande número de construções de alternância, se ele inclui construções de alternação aninhadas ou, mais comumente, se ele inclui quantificadores aninhados de opcionais, o número de operações de comparação devem corresponder a um padrão de expressão regular pode aumentar exponencialmente. Por exemplo, o padrão de expressão regular ^(a+)+$ foi projetado para corresponder uma cadeia completa que contém um ou mais "a" caracteres. O exemplo fornece duas seqüências de caracteres de entrada de tamanho idêntico, mas apenas a primeira seqüência de caracteres corresponde ao padrão. O System.Diagnostics.Stopwatch classe é usada para determinar quanto tempo a correspondência operação demora.

Imports System.Diagnostics
Imports System.Text.RegularExpressions

Module Example
   Public Sub Main()
      Dim pattern As String = "^(a+)+$"
      Dim inputs() As String = { "aaaaaa", "aaaaa!" }
      Dim rgx As New Regex(pattern)
      Dim sw As Stopwatch

      For Each input As String In inputs
         sw = Stopwatch.StartNew()   
         Dim match As Match = rgx.Match(input)
         sw.Stop()
         If match.Success Then
            Console.WriteLine("Matched {0} in {1}", match.Value, sw.Elapsed)
         Else
            Console.WriteLine("No match found in {0}", sw.Elapsed)
         End If      
      Next
   End Sub
End Module
using System;
using System.Diagnostics;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = "^(a+)+$";
      string[] inputs = { "aaaaaa", "aaaaa!" };
      Regex rgx = new Regex(pattern);
      Stopwatch sw;

      foreach (string input in inputs) {
         sw = Stopwatch.StartNew();   
         Match match = rgx.Match(input);
         sw.Stop();
         if (match.Success)
            Console.WriteLine("Matched {0} in {1}", match.Value, sw.Elapsed);
         else
            Console.WriteLine("No match found in {0}", sw.Elapsed);
      }
   }
}

Como a saída do exemplo mostra, o mecanismo de expressão regular levou cerca de duas vezes como tempo localizar uma seqüência de caracteres de entrada não correspondeu ao padrão de como ele fez para identificar uma seqüência correspondente. Isso ocorre porque uma correspondência malsucedida sempre representa um cenário de pior caso. O mecanismo de expressão regular deve usar a expressão regular a seguir todos os caminhos possíveis por meio de dados antes que ele possa concluir que a correspondência for bem-sucedida e os parênteses aninhados criar muitos caminhos adicionais por meio de dados. O mecanismo de expressão regular conclui que a segunda seqüência de caracteres não correspondeu ao padrão, fazendo o seguinte:

  • Ele verifica que era no início da seqüência de caracteres e, em seguida, correspondências cinco primeiros caracteres na seqüência de caracteres com o padrão a+. Em seguida, determina que não existem grupos adicionais de "a" caracteres na seqüência. Finalmente, ele testa o final da seqüência de caracteres. Porque um carácter adicional permanece na seqüência de caracteres, a correspondência falha. Essa falha na correspondência requer 9 comparações. O mecanismo de expressões regulares também salva informações de estado de suas correspondências de "a" (que chamaremos corresponde a 1), "aa" (coincidir 2), "aaa" (correspondem a 3) e "aaaa" (correspondem a 4).

  • Ele retorna para a partida salva anteriormente 4. Ele determina que há um adicionais "a" caractere para atribuir a um grupo de capturados adicional. Finalmente, ele testa o final da seqüência de caracteres. Porque um carácter adicional permanece na seqüência de caracteres, a correspondência falha. Essa falha na correspondência requer 4 comparações. Até então, um total de comparações de 13 ter sido executada.

  • Ele retorna para a partida salva anteriormente 3. Ele determina que existem dois adicionais "a" caracteres para atribuir a um grupo de capturados adicional. No entanto, o teste de final de seqüência de caracteres falhará. Em seguida, retorna ao match3 e tenta corresponder os dois adicionais "a" caracteres de dois grupos são capturadas. O final da seqüência de teste ainda falha. Essas correspondências com falha exigem 12 comparações. Até então, um total de 25 comparações ter sido executada.

Comparação de seqüência de entrada com a expressão regular continua dessa maneira até que o mecanismo de expressão regular tentou todas as combinações possíveis de correspondências e, em seguida, conclui que não há nenhuma correspondência. Devido os quantificadores aninhados, essa comparação é um O(2n) ou uma operação exponencial, onde n é o número de caracteres na seqüência de entrada. Isso significa que, na pior das hipóteses, uma seqüência de caracteres de entrada de 30 caracteres requer aproximadamente 1.073.741.824 comparações, e uma cadeia de 40 caracteres de entrada requer aproximadamente 1,099,511,627,776 comparações. Se você usar seqüências de caracteres desses ou comprimentos ainda maiores, os métodos de expressão regular podem levar muito tempo para concluir quando eles processam a entrada que não corresponde ao padrão de expressão regular.

Voltar ao topo

Controlando o Backtracking

Backtracking permite que você crie poderosas e flexíveis de expressões regulares. No entanto, como a seção anterior mostrada, esses benefícios podem ser combinados com o desempenho fraco demais. A.NET Framework oferece suporte a três elementos de linguagem de expressão regular que limitar ou suprimir backtracking e oferecer suporte a expressões regulares complexas com pouca ou nenhuma penalidade de desempenho: subexpressões nonbacktracking, declarações de lookbehind, e lookahead asserções. Para obter mais informações sobre cada elemento de linguagem, consulte Agrupando Construtores.

Subexpressão nonbacktracking

O (?> subexpressão) elemento de linguagem suprime backtracking em uma subexpressão. É útil para evitar problemas de desempenho associados a correspondências com falha.

O exemplo a seguir ilustra como a supressão de backtracking melhora o desempenho quando usando quantificadores aninhados. Ele mede o tempo necessário para o mecanismo de expressões regulares determinar que uma seqüência de caracteres de entrada não corresponde a duas expressões regulares. A primeira expressão regular usa backtracking para tentar corresponder a uma seqüência de caracteres que contém uma ou mais ocorrências de um ou mais dígitos hexadecimais, seguidos de dois pontos, seguido por um ou mais dígitos hexadecimais, seguido por dois dois-pontos. A segunda expressão regular é idêntica ao primeiro, exceto que ela desabilita backtracking. Como mostra a saída do exemplo, a melhoria de desempenho desabilitem o backtracking é significativa.

Imports System.Diagnostics
Imports System.Text.RegularExpressions

Module Example
   Public Sub Main()
      Dim input As String = "b51:4:1DB:9EE1:5:27d60:f44:D4:cd:E:5:0A5:4a:D24:41Ad:"
      Dim matched As Boolean
      Dim sw As Stopwatch

      Console.WriteLine("With backtracking:")
      Dim backPattern As String = "^(([0-9a-fA-F]{1,4}:)*([0-9a-fA-F]{1,4}))*(::)$"
      sw = Stopwatch.StartNew()
      matched = Regex.IsMatch(input, backPattern)
      sw.Stop()
      Console.WriteLine("Match: {0} in {1}", Regex.IsMatch(input, backPattern), sw.Elapsed)
      Console.WriteLine()

      Console.WriteLine("Without backtracking:")
      Dim noBackPattern As String = "^((?>[0-9a-fA-F]{1,4}:)*(?>[0-9a-fA-F]{1,4}))*(::)$"
      sw = Stopwatch.StartNew()
      matched = Regex.IsMatch(input, noBackPattern)
      sw.Stop()
      Console.WriteLine("Match: {0} in {1}", Regex.IsMatch(input, noBackPattern), sw.Elapsed)
   End Sub
End Module
' The example displays the following output:
'       With backtracking:
'       Match: False in 00:00:27.4282019
'       
'       Without backtracking:
'       Match: False in 00:00:00.0001391
using System;
using System.Diagnostics;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string input = "b51:4:1DB:9EE1:5:27d60:f44:D4:cd:E:5:0A5:4a:D24:41Ad:";
      bool matched;
      Stopwatch sw;

      Console.WriteLine("With backtracking:");
      string backPattern = "^(([0-9a-fA-F]{1,4}:)*([0-9a-fA-F]{1,4}))*(::)$";
      sw = Stopwatch.StartNew();
      matched = Regex.IsMatch(input, backPattern);
      sw.Stop();
      Console.WriteLine("Match: {0} in {1}", Regex.IsMatch(input, backPattern), sw.Elapsed);
      Console.WriteLine();

      Console.WriteLine("Without backtracking:");
      string noBackPattern = "^((?>[0-9a-fA-F]{1,4}:)*(?>[0-9a-fA-F]{1,4}))*(::)$";
      sw = Stopwatch.StartNew();
      matched = Regex.IsMatch(input, noBackPattern);
      sw.Stop();
      Console.WriteLine("Match: {0} in {1}", Regex.IsMatch(input, noBackPattern), sw.Elapsed);
   }
}
// The example displays output like the following:
//       With backtracking:
//       Match: False in 00:00:27.4282019
//       
//       Without backtracking:
//       Match: False in 00:00:00.0001391

Declarações de Lookbehind

A.NET Framework inclui dois elementos de linguagem, (?<=subexpressão) e (?<!subexpressão), que coincidam com o anterior ou mais caracteres na seqüência de entrada. Os dois elementos de linguagem são declarações de largura zero; ou seja, eles determinam se o caractere ou caracteres que deve preceder imediatamente o caractere atual podem ser correspondidos por subexpressão, sem avançando ou backtracking.

(?<=subexpressão) é uma declaração de lookbehind positivo; ou seja, o caractere ou caracteres antes da posição atual deve coincidir com subexpressão. (?<!subexpressão) é uma declaração de lookbehind negativo; ou seja, o caractere ou caracteres antes da posição atual não deve corresponder subexpressão. Ambas as declarações de lookbehind positivos e negativos são mais úteis quando subexpressão é um subconjunto da subexpressão anterior.

O exemplo a seguir usa dois padrões de equivalentes de expressão regular para validar o nome de usuário em um endereço de email. O primeiro padrão é sujeita a mau desempenho devido backtracking excessiva. O segundo padrão modifica a primeira expressão regular, substituindo um quantificador aninhado com uma declaração lookbehind positivo. A saída do exemplo exibe o tempo de execução da Regex.IsMatch método.

Module Example
   Public Sub Main()
      Dim sw As Stopwatch
      Dim input As String = "aaaaaaaaaaaaaaaaaaaa"
      Dim result As Boolean

      Dim pattern As String = "^[0-9A-Z]([-.\w]*[0-9A-Z])?@"
      sw = Stopwatch.StartNew()
      result = Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase)
      sw.Stop()
      Console.WriteLine("Match: {0} in {1}", result, sw.Elapsed)

      Dim behindPattern As String = "^[0-9A-Z][-.\w]*(?<=[0-9A-Z])@"
      sw = Stopwatch.StartNew()
      result = Regex.IsMatch(input, behindPattern, RegexOptions.IgnoreCase)
      sw.Stop()
      Console.WriteLine("Match with Lookbehind: {0} in {1}", result, sw.Elapsed)
   End Sub
End Module
' The example displays the following output:
'       Match: True in 00:00:00.0017549
'       Match with Lookbehind: True in 00:00:00.0000659
using System;
using System.Diagnostics;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      Stopwatch sw;
      string input = "aaaaaaaaaaaaaaaaaaaa";
      bool result;

      string pattern = @"^[0-9A-Z]([-.\w]*[0-9A-Z])?@";
      sw = Stopwatch.StartNew();
      result = Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase);
      sw.Stop();
      Console.WriteLine("Match: {0} in {1}", result, sw.Elapsed);

      string behindPattern = @"^[0-9A-Z][-.\w]*(?<=[0-9A-Z])@";
      sw = Stopwatch.StartNew();
      result = Regex.IsMatch(input, behindPattern, RegexOptions.IgnoreCase);
      sw.Stop();
      Console.WriteLine("Match with Lookbehind: {0} in {1}", result, sw.Elapsed);
   }
}
// The example displays the following output:
//       Match: True in 00:00:00.0017549
//       Match with Lookbehind: True in 00:00:00.0000659

O primeiro padrão de expressão regular, ^[0-9A-Z]([-.\w]*[0-9A-Z])*@, que é definido como mostrado na tabela a seguir.

Padrão

Descrição

^

Inicie a correspondência no início da seqüência de caracteres.

[0-9A-Z]

Corresponde a um caractere alfanumérico. Essa comparação é diferencia maiúsculas de minúsculas, porque o Regex.IsMatch método é chamado com o RegexOptions.IgnoreCase opção.

[-. \w]*

Corresponde a zero, um ou mais ocorrências de um hífen, o período ou o caractere de palavra.

[0-9A-Z]

Corresponde a um caractere alfanumérico.

([-. \w]*[0-9A-Z])*

Corresponde a zero ou mais ocorrências da combinação de zero ou mais hífens, pontos ou caracteres de palavra, seguidos por um caractere alfanumérico. Este é o primeiro grupo de capturando.

@

Correspondência uma arroba ("@").

O segundo padrão de expressão regular, ^[0-9A-Z][-.\w]*(?<=[0-9A-Z])@, usa uma declaração lookbehind positivo. Ele é definido como mostrado na tabela a seguir.

Padrão

Descrição

^

Inicie a correspondência no início da seqüência de caracteres.

[0-9A-Z]

Corresponde a um caractere alfanumérico. Essa comparação é diferencia maiúsculas de minúsculas, porque o Regex.IsMatch método é chamado com o RegexOptions.IgnoreCase opção.

[-. \w]*

Corresponde a zero ou mais ocorrências de um hífen, o período ou o caractere de palavra.

(?<=[0-9A-Z])

Olhar novamente o último caractere correspondente e continuar a correspondência se for alfanumérico. Observe que os caracteres alfanuméricos são um subconjunto do conjunto que consiste em todos os caracteres alfabéticos, hífens e pontos.

@

Correspondência uma arroba ("@").

Lookahead asserções

A.NET Framework inclui dois elementos de linguagem, (?=subexpressão) e (?!subexpressão), que coincidam com o próximo caractere ou caracteres na seqüência de entrada. Os dois elementos de linguagem são declarações de largura zero; ou seja, eles determinam se o caractere ou caracteres a seguem imediatamente o caractere atual podem ser correspondidos por subexpressão, sem avançando ou backtracking.

(?=subexpressão) é uma afirmação lookahead positivo; ou seja, o caractere ou caracteres após a posição atual deve coincidir com subexpressão. (?!subexpressão) é uma afirmação lookahead negativo; ou seja, o caractere ou caracteres após a posição atual não deve corresponder subexpressão. As duas afirmações lookahead positivo e negativo são mais úteis quando subexpressão é um subconjunto da próxima subexpressão.

O exemplo a seguir usa dois padrões de equivalentes de expressão regular para validar um nome de tipo totalmente qualificado. O primeiro padrão é sujeita a mau desempenho devido backtracking excessiva. O segundo modifica a primeira expressão regular, substituindo um quantificador aninhado com uma afirmação lookahead positivo. A saída do exemplo exibe o tempo de execução da Regex.IsMatch método.

Imports System.Diagnostics
Imports System.Text.RegularExpressions

Module Example
   Public Sub Main()
      Dim input As String = "aaaaaaaaaaaaaaaaaaaaaa."
      Dim result As Boolean
      Dim sw As Stopwatch

      Dim pattern As String = "^(([A-Z]\w*)+\.)*[A-Z]\w*$"
      sw = Stopwatch.StartNew()
      result = Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase)
      sw.Stop()
      Console.WriteLine("{0} in {1}", result, sw.Elapsed)

      Dim aheadPattern As String = "^((?=[A-Z])\w+\.)*[A-Z]\w*$"
      sw = Stopwatch.StartNew()
      result = Regex.IsMatch(input, aheadPattern, RegexOptions.IgnoreCase)
      sw.Stop()
      Console.WriteLine("{0} in {1}", result, sw.Elapsed)
   End Sub
End Module
' The example displays the following output:
'       False in 00:00:03.8003793
'       False in 00:00:00.0000866
using System;
using System.Diagnostics;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string input = "aaaaaaaaaaaaaaaaaaaaaa.";
      bool result;
      Stopwatch sw;

      string pattern = @"^(([A-Z]\w*)+\.)*[A-Z]\w*$";
      sw = Stopwatch.StartNew();
      result = Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase);
      sw.Stop();
      Console.WriteLine("{0} in {1}", result, sw.Elapsed);

      string aheadPattern = @"^((?=[A-Z])\w+\.)*[A-Z]\w*$";
      sw = Stopwatch.StartNew();
      result = Regex.IsMatch(input, aheadPattern, RegexOptions.IgnoreCase);
      sw.Stop();
      Console.WriteLine("{0} in {1}", result, sw.Elapsed);
   }
}
// The example displays the following output:
//       False in 00:00:03.8003793
//       False in 00:00:00.0000866

O primeiro padrão de expressão regular, ^(([A-Z]\w*)+\.)*[A-Z]\w*$, que é definido como mostrado na tabela a seguir.

Padrão

Descrição

^

Inicie a correspondência no início da seqüência de caracteres.

([A-Z]\w*)+\.

Correspondência de um caractere alfabético (A-Z) seguido da palavra de zero ou mais caracteres em um ou mais vezes, seguido por um período. Essa comparação é diferencia maiúsculas de minúsculas, porque o Regex.IsMatch método é chamado com o RegexOptions.IgnoreCase opção.

(([A-Z]\w*)+\.)*

Coincide com o padrão anterior zero ou mais vezes.

[A-Z]\w*

Corresponde a um caractere alfabético, seguido de zero ou mais caracteres do word.

$

Finalize a correspondência no final da seqüência de entrada.

O segundo padrão de expressão regular, ^((?=[A-Z])\w+\.)*[A-Z]\w*$, usa uma declaração lookahead positivo. Ele é definido como mostrado na tabela a seguir.

Padrão

Descrição

^

Inicie a correspondência no início da seqüência de caracteres.

(?=[A-Z])

Olhar à frente para o primeiro caractere e continuar a correspondência se ele estiver em ordem alfabética (A-Z). Essa comparação é diferencia maiúsculas de minúsculas, porque o Regex.IsMatch método é chamado com o RegexOptions.IgnoreCase opção.

\w+\.

Corresponde a um ou mais caracteres do word, seguidos por um período.

((?=[A-Z])\w+\.)*

Coincide com o padrão de um ou mais caracteres do word, seguido por um ponto zero ou mais vezes. O caractere da palavra inicial deve estar em ordem alfabética.

[A-Z]\w*

Corresponde a um caractere alfabético, seguido de zero ou mais caracteres do word.

$

Finalize a correspondência no final da seqüência de entrada.

Voltar ao topo

Consulte também

Referência

Quantificadores

Construtores de Alternância

Agrupando Construtores

Conceitos

Expressões Regulares do .NET Framework

Elementos de linguagem das expressões regulares

Outros recursos

Práticas recomendadas para expressões regulares na.NET Framework