Opções de expressões regulares

Por padrão, a comparação de uma cadeia de caracteres de entrada com quaisquer caracteres literais em um padrão de expressão regular diferencia maiúsculas e minúsculas; o espaço em branco em um padrão de expressão regular é interpretado como caracteres de espaço em branco literais e os grupos de captura em uma expressão regular são nomeados implícita e explicitamente. É possível modificar esses e vários outros aspectos do comportamento de expressão regular especificando opções de expressões regulares. Algumas dessas opções, que estão listadas na tabela a seguir, podem ser incluídas embutidas como parte do padrão de expressão regular, ou podem ser fornecidas a um construtor de classe System.Text.RegularExpressions.Regex ou método de correspondência padrão estático como um valor de enumeração System.Text.RegularExpressions.RegexOptions.

Membro do RegexOptions Caractere embutido Efeito Mais informações
None Não disponível Use o comportamento padrão. Opções padrão
IgnoreCase i Use correspondência sem diferenciação de maiúsculas e minúsculas. Correspondência sem diferenciação entre maiúsculas e minúsculas
Multiline m Use o modo multilinha, em que ^ e $ indicam o início e o fim de cada linha (em vez do início e o fim da cadeia de caracteres de entrada). Modo multilinha
Singleline s Use o modo de linha única, em que o ponto (.) corresponde com todos os caracteres (em vez de todos os caracteres, exceto \n). Modo de linha única
ExplicitCapture n Não capture grupos sem nome. As únicas capturas válidas são grupos explicitamente nomeados ou numerados na forma (?<name>subexpression). Apenas capturas explícitas
Compiled Não disponível Compile a expressão regular para um assembly. Expressões regulares compiladas
IgnorePatternWhitespace x Exclua um espaço em branco sem escape do padrão e habilite comentários após uma tecla de cerquilha (#). Ignorar espaço em branco
RightToLeft Não disponível Altera a direção da pesquisa. A pesquisa se move da direita para a esquerda, em vez de da esquerda para a direita. Modo da direita para a esquerda
ECMAScript Não disponível Habilite o comportamento compatível com ECMAScript para a expressão. Comportamento de correspondência de ECMAScript
CultureInvariant Não disponível Ignorar diferenças culturais no idioma. Comparação usando a cultura invariável
NonBacktracking Não disponível Faça a correspondência usando uma abordagem que evita o rastreamento inverso e garante o processamento de tempo linear no comprimento da entrada. (Disponível no .NET 7 e versões posteriores.) Modo sem rastreamento inverso

Especificar opções

É possível especificar opções para expressões regulares de uma destas três maneiras:

  • No parâmetro options de um construtor de classe System.Text.RegularExpressions.Regex ou método de correspondência padrão (Shared no Visual Basic) estático, como Regex(String, RegexOptions) ou Regex.Match(String, String, RegexOptions). O parâmetro options é uma combinação OR bit a bit de valores enumerados System.Text.RegularExpressions.RegexOptions.

    Quando as opções são fornecidas a uma instância Regex mediante uso do parâmetro options de um construtor de classe, elas são atribuídas à propriedade System.Text.RegularExpressions.RegexOptions. No entanto, a propriedade System.Text.RegularExpressions.RegexOptions não reflete opções embutidas no próprio padrão de expressão regular.

    O exemplo a seguir ilustra esse cenário. Ele usa o parâmetro options do método Regex.Match(String, String, RegexOptions) para habilitar correspondência sem diferenciação entre maiúsculas e minúsculas e ignorar espaço em branco do parâmetro ao identificar palavras que começam com a letra "d".

    string pattern = @"d \w+ \s";
    string input = "Dogs are decidedly good pets.";
    RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace;
    
    foreach (Match match in Regex.Matches(input, pattern, options))
        Console.WriteLine("'{0}// found at index {1}.", match.Value, match.Index);
    // The example displays the following output:
    //    'Dogs // found at index 0.
    //    'decidedly // found at index 9.
    
    Dim pattern As String = "d \w+ \s"
    Dim input As String = "Dogs are decidedly good pets."
    Dim options As RegexOptions = RegexOptions.IgnoreCase Or RegexOptions.IgnorePatternWhitespace
    
    For Each match As Match In Regex.Matches(input, pattern, options)
        Console.WriteLine("'{0}' found at index {1}.", match.Value, match.Index)
    Next
    ' The example displays the following output:
    '    'Dogs ' found at index 0.
    '    'decidedly ' found at index 9.      
    
  • Aplicando opções embutidas em um padrão de expressão regular com a sintaxe (?imnsx-imnsx). A opção se aplica ao padrão do ponto em que a opção é definida até o fim do padrão ou o ponto em que a opção tem é indefinida por outra opção embutida. Observe que a propriedade System.Text.RegularExpressions.RegexOptions de uma instância Regex não reflete essas opções embutidas. Para saber mais, confira o tópico Constructos diversos.

    O exemplo a seguir ilustra esse cenário. Ele usa opções embutidas para habilitar a correspondência sem diferenciação entre maiúsculas e minúsculas e ignorar o espaço em branco do padrão ao identificar palavras que começam com a letra “d”.

    string pattern = @"(?ix) d \w+ \s";
    string input = "Dogs are decidedly good pets.";
    
    foreach (Match match in Regex.Matches(input, pattern))
        Console.WriteLine("'{0}// found at index {1}.", match.Value, match.Index);
    // The example displays the following output:
    //    'Dogs // found at index 0.
    //    'decidedly // found at index 9.
    
    Dim pattern As String = "\b(?ix) d \w+ \s"
    Dim input As String = "Dogs are decidedly good pets."
    
    For Each match As Match In Regex.Matches(input, pattern)
        Console.WriteLine("'{0}' found at index {1}.", match.Value, match.Index)
    Next
    ' The example displays the following output:
    '    'Dogs ' found at index 0.
    '    'decidedly ' found at index 9.      
    
  • Aplicando opções embutidas em um constructo de agrupamento em particular em um padrão de expressão regular com a sintaxe (?imnsx-imnsx:subexpressão). Nenhum sinal antes de um conjunto de opções ativa o conjunto; um sinal de subtração antes de um conjunto de opções desativa o conjunto. (? é uma parte fixa da sintaxe do constructo do idioma exigida com as opções habilitadas ou desabilitadas). A opção se aplica somente a esse grupo. Para saber mais, confira Constructos de agrupamento.

    O exemplo a seguir ilustra esse cenário. Ele usa opções embutidas em um constructo de agrupamento para habilitar a correspondência sem diferenciação entre maiúsculas e minúsculas e ignorar espaço em branco do padrão ao identificar palavras que começam com a letra “d”.

    string pattern = @"\b(?ix: d \w+)\s";
    string input = "Dogs are decidedly good pets.";
    
    foreach (Match match in Regex.Matches(input, pattern))
        Console.WriteLine("'{0}// found at index {1}.", match.Value, match.Index);
    // The example displays the following output:
    //    'Dogs // found at index 0.
    //    'decidedly // found at index 9.
    
    Dim pattern As String = "\b(?ix: d \w+)\s"
    Dim input As String = "Dogs are decidedly good pets."
    
    For Each match As Match In Regex.Matches(input, pattern)
        Console.WriteLine("'{0}' found at index {1}.", match.Value, match.Index)
    Next
    ' The example displays the following output:
    '    'Dogs ' found at index 0.
    '    'decidedly ' found at index 9.      
    

Se as opções forem embutidas especificadas, um sinal de menos (-) antes de uma opção ou conjunto de opções desativa essas opções. Por exemplo, a construção embutida (?ix-ms) ativa as opções RegexOptions.IgnoreCase e RegexOptions.IgnorePatternWhitespace e desativa as opções RegexOptions.Multiline e RegexOptions.Singleline. Todas as opções de expressões regulares são desativadas por padrão.

Observação

Se as opções de expressão regular especificadas no parâmetro options de uma chamada de construtor ou método entrar em conflito com as opções especificadas embutidas em um padrão de expressão regular, serão usadas as opções embutidas.

As cinco opções de expressão regular a seguir podem ser definidas com parâmetro de opções e embutidas:

As cinco opções de expressão regular a seguir podem ser definidas usando o parâmetro options, mas não podem ser definidas embutidas:

Determinar opções

É possível determinar que opções foram fornecidas a um objeto Regex quando ele tiver sido instanciado recuperando o valor da propriedade Regex.Options somente leitura. Essa propriedade é particularmente útil para determinar as opções definidas para uma expressão regular compilada criada pelo método Regex.CompileToAssembly.

Para testar a presença de qualquer opção, exceto RegexOptions.None, realize uma operação AND com o valor da propriedade Regex.Options e o valor RegexOptions no qual você está interessado. Em seguida, teste se o resultado é igual ao valor de RegexOptions. O exemplo a seguir testa se a opção RegexOptions.IgnoreCase foi definida.

if ((rgx.Options & RegexOptions.IgnoreCase) == RegexOptions.IgnoreCase)
    Console.WriteLine("Case-insensitive pattern comparison.");
else
    Console.WriteLine("Case-sensitive pattern comparison.");
If (rgx.Options And RegexOptions.IgnoreCase) = RegexOptions.IgnoreCase Then
    Console.WriteLine("Case-insensitive pattern comparison.")
Else
    Console.WriteLine("Case-sensitive pattern comparison.")
End If

Para testar RegexOptions.None, determine se o valor da propriedade Regex.Options é igual a RegexOptions.None, como ilustra o exemplo a seguir.

if (rgx.Options == RegexOptions.None)
    Console.WriteLine("No options have been set.");
If rgx.Options = RegexOptions.None Then
    Console.WriteLine("No options have been set.")
End If

As seções a seguir listam as opções com suporte na expressão regular no .NET.

Opções padrão

A opção RegexOptions.None indica que nenhuma opção foi especificada, e o mecanismo de expressão regular usa seu comportamento padrão. Isso inclui o seguinte:

  • O padrão é interpretado como canônico e não como uma expressão regular ECMAScript.

  • O padrão da expressão regular é combinado na cadeia de caracteres de entrada da esquerda para a direita.

  • As comparações diferenciam maiúsculas de minúsculas.

  • Os elementos de linguagem ^ e $ indicam o início e o fim da cadeia de caracteres de entrada. O final da cadeia de caracteres de entrada pode ser um caractere de nova linha \n à direita.

  • O elemento de linguagem . corresponde com todos os caracteres, exceto \n.

  • Qualquer espaço em branco em um padrão de expressão regular é interpretado como caractere de espaço literal.

  • As convenções da cultura atual são usadas ao comparar o padrão com a cadeia de caracteres de entrada.

  • Os grupos de capturas no padrão de expressão regular são implícitos e explícitos.

Observação

A opção RegexOptions.None não tem equivalente embutido. Quando as opções de expressões regulares são embutidas aplicadas, o comportamento padrão é restaurado de modo opção a opção, desativando uma opção em particular. Por exemplo, (?i) ativa a comparação sem diferenciar maiúsculas de minúsculas e (?-i) restaura a comparação que diferencia maiúsculas de minúsculas.

Como a opção RegexOptions.None representa o comportamento padrão do mecanismo de expressão regular, raramente, ela é explicitamente especificada em uma chamada de método. Em vez disso, é chamado um método de construtor ou de correspondência padrão estático sem um parâmetro options.

Correspondência sem diferenciação entre maiúsculas e minúsculas

A opção IgnoreCase ou a opção embutida i fornece correspondência sem diferenciação entre maiúsculas e minúsculas. Por padrão, são usadas as convenções de diferenciação entre maiúsculas e minúsculas da cultura atual.

O exemplo a seguir define um padrão de expressão regular, \bthe\w*\b, que corresponde a todas as palavras que começam com “the”. Como a primeira chamada para o método Match usa a comparação que diferencia maiúsculas de minúsculas padrão, a saída indica que a cadeia de caracteres "The", que inicia a frase, não é combinada. Ela é combinada quando o método Match é chamado com opções definidas para IgnoreCase.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"\bthe\w*\b";
      string input = "The man then told them about that event.";
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine("Found {0} at index {1}.", match.Value, match.Index);

      Console.WriteLine();
      foreach (Match match in Regex.Matches(input, pattern,
                                            RegexOptions.IgnoreCase))
         Console.WriteLine("Found {0} at index {1}.", match.Value, match.Index);
   }
}
// The example displays the following output:
//       Found then at index 8.
//       Found them at index 18.
//
//       Found The at index 0.
//       Found then at index 8.
//       Found them at index 18.
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "\bthe\w*\b"
        Dim input As String = "The man then told them about that event."
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("Found {0} at index {1}.", match.Value, match.Index)
        Next
        Console.WriteLine()
        For Each match As Match In Regex.Matches(input, pattern, _
                                                 RegexOptions.IgnoreCase)
            Console.WriteLine("Found {0} at index {1}.", match.Value, match.Index)
        Next
    End Sub
End Module
' The example displays the following output:
'       Found then at index 8.
'       Found them at index 18.
'       
'       Found The at index 0.
'       Found then at index 8.
'       Found them at index 18.

O exemplo a seguir modifica o padrão da expressão regular do exemplo anterior para usar opções embutidas, em vez do parâmetro options para fornecer comparação de diferenciação entre maiúsculas e minúsculas. O primeiro padrão define a opção que não diferencia maiúsculas de minúsculas em um constructo de agrupamento que se aplica apenas à letra “t” na cadeia de caracteres “the”. Como o constructo da opção ocorre no início do padrão, o segundo padrão aplica a opção que não diferencia maiúsculas de minúsculas a toda a expressão regular.

using System;
using System.Text.RegularExpressions;

public class CaseExample
{
    public static void Main()
    {
        string pattern = @"\b(?i:t)he\w*\b";
        string input = "The man then told them about that event.";
        foreach (Match match in Regex.Matches(input, pattern))
            Console.WriteLine("Found {0} at index {1}.", match.Value, match.Index);

        Console.WriteLine();
        pattern = @"(?i)\bthe\w*\b";
        foreach (Match match in Regex.Matches(input, pattern,
                                              RegexOptions.IgnoreCase))
            Console.WriteLine("Found {0} at index {1}.", match.Value, match.Index);
    }
}
// The example displays the following output:
//       Found The at index 0.
//       Found then at index 8.
//       Found them at index 18.
//
//       Found The at index 0.
//       Found then at index 8.
//       Found them at index 18.
Imports System.Text.RegularExpressions

Module CaseExample
    Public Sub Main()
        Dim pattern As String = "\b(?i:t)he\w*\b"
        Dim input As String = "The man then told them about that event."
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("Found {0} at index {1}.", match.Value, match.Index)
        Next
        Console.WriteLine()
        pattern = "(?i)\bthe\w*\b"
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("Found {0} at index {1}.", match.Value, match.Index)
        Next
    End Sub
End Module

' The example displays the following output:
'       Found The at index 0.
'       Found then at index 8.
'       Found them at index 18.
'       
'       Found The at index 0.
'       Found then at index 8.
'       Found them at index 18.

Modo multilinha

A opção RegexOptions.Multiline ou a opção embutida m habilita o mecanismo de expressão regular para processar uma cadeia de caracteres de entrada que consiste em várias linhas. Ele altera a interpretação dos elementos de linguagem ^ e $ para que indiquem o início e o fim de uma linha, em vez de o início e o fim da cadeia de caracteres de entrada.

Por padrão, $ será atendido somente no final da cadeia de caracteres de entrada. Se você especificar a opção RegexOptions.Multiline, ela será atendida pelo caractere de nova linha (\n) ou com o fim da cadeia de caracteres de entrada.

Em nenhum dos casos, $ reconhece a combinação de caracteres de retorno de carro/feed de linha (\r\n). $ sempre ignora qualquer retorno de carro (\r). Para encerrar a correspondência com \r\n ou \n, use a subexpressão \r?$ em vez de apenas $. Observe que isso fará a parte \r da correspondência.

O exemplo a seguir extrai nomes e pontuações de jogadores de boliche e os adiciona a uma coleção SortedList<TKey,TValue>, que os classifica em ordem decrescente. O método Matches é chamado duas vezes. Na primeira chamada do método, a expressão regular é ^(\w+)\s(\d+)$ e nenhuma opção é definida. Como a saída mostra, uma vez que o mecanismo de expressões regulares não pode corresponder ao padrão de entrada junto com o início e o fim da cadeia de caracteres de entrada, nenhuma correspondência é encontrada. Na segunda chamada do método, a expressão regular é alterada para ^(\w+)\s(\d+)\r?$ e as opções são definidas para RegexOptions.Multiline. Como a saída mostra, os nomes e pontuações são combinados com sucesso e as pontuações são exibidas em ordem decrescente.

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

public class Multiline1Example
{
    public static void Main()
    {
        SortedList<int, string> scores = new SortedList<int, string>(new DescendingComparer1<int>());

        string input = "Joe 164\n" +
                       "Sam 208\n" +
                       "Allison 211\n" +
                       "Gwen 171\n";
        string pattern = @"^(\w+)\s(\d+)$";
        bool matched = false;

        Console.WriteLine("Without Multiline option:");
        foreach (Match match in Regex.Matches(input, pattern))
        {
            scores.Add(Int32.Parse(match.Groups[2].Value), (string)match.Groups[1].Value);
            matched = true;
        }
        if (!matched)
            Console.WriteLine("   No matches.");
        Console.WriteLine();

        // Redefine pattern to handle multiple lines.
        pattern = @"^(\w+)\s(\d+)\r*$";
        Console.WriteLine("With multiline option:");
        foreach (Match match in Regex.Matches(input, pattern, RegexOptions.Multiline))
            scores.Add(Int32.Parse(match.Groups[2].Value), (string)match.Groups[1].Value);

        // List scores in descending order.
        foreach (KeyValuePair<int, string> score in scores)
            Console.WriteLine("{0}: {1}", score.Value, score.Key);
    }
}

public class DescendingComparer1<T> : IComparer<T>
{
    public int Compare(T x, T y)
    {
        return Comparer<T>.Default.Compare(x, y) * -1;
    }
}
// The example displays the following output:
//   Without Multiline option:
//      No matches.
//
//   With multiline option:
//   Allison: 211
//   Sam: 208
//   Gwen: 171
//   Joe: 164
Imports System.Collections.Generic
Imports System.Text.RegularExpressions

Module Multiline1Example
    Public Sub Main()
        Dim scores As New SortedList(Of Integer, String)(New DescendingComparer1(Of Integer)())

        Dim input As String = "Joe 164" + vbCrLf +
                              "Sam 208" + vbCrLf +
                              "Allison 211" + vbCrLf +
                              "Gwen 171" + vbCrLf
        Dim pattern As String = "^(\w+)\s(\d+)$"
        Dim matched As Boolean = False

        Console.WriteLine("Without Multiline option:")
        For Each match As Match In Regex.Matches(input, pattern)
            scores.Add(CInt(match.Groups(2).Value), match.Groups(1).Value)
            matched = True
        Next
        If Not matched Then Console.WriteLine("   No matches.")
        Console.WriteLine()

        ' Redefine pattern to handle multiple lines.
        pattern = "^(\w+)\s(\d+)\r*$"
        Console.WriteLine("With multiline option:")
        For Each match As Match In Regex.Matches(input, pattern, RegexOptions.Multiline)
            scores.Add(CInt(match.Groups(2).Value), match.Groups(1).Value)
        Next
        ' List scores in descending order. 
        For Each score As KeyValuePair(Of Integer, String) In scores
            Console.WriteLine("{0}: {1}", score.Value, score.Key)
        Next
    End Sub
End Module

Public Class DescendingComparer1(Of T) : Implements IComparer(Of T)
    Public Function Compare(x As T, y As T) As Integer _
           Implements IComparer(Of T).Compare
        Return Comparer(Of T).Default.Compare(x, y) * -1
    End Function
End Class
' The example displays the following output:
'    Without Multiline option:
'       No matches.
'    
'    With multiline option:
'    Allison: 211
'    Sam: 208
'    Gwen: 171
'    Joe: 164

O padrão de expressão regular ^(\w+)\s(\d+)\r*$ é definido conforme mostrado na tabela a seguir.

Padrão Descrição
^ Começar no início da linha.
(\w+) Fazer a correspondência a um ou mais caracteres de palavra. Este é o primeiro grupo de captura.
\s Corresponde a um caractere de espaço em branco.
(\d+) Corresponde a um ou mais dígitos decimais. Este é o segundo grupo de captura.
\r? Corresponder a zero ou um caractere de retorno de carro.
$ Terminar no fim da linha.

O exemplo a seguir é equivalente ao anterior, exceto que ele usa a opção embutida (?m) para definir a opção de multilinhas.

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

public class Multiline2Example
{
    public static void Main()
    {
        SortedList<int, string> scores = new SortedList<int, string>(new DescendingComparer<int>());

        string input = "Joe 164\n" +
                       "Sam 208\n" +
                       "Allison 211\n" +
                       "Gwen 171\n";
        string pattern = @"(?m)^(\w+)\s(\d+)\r*$";

        foreach (Match match in Regex.Matches(input, pattern, RegexOptions.Multiline))
            scores.Add(Convert.ToInt32(match.Groups[2].Value), match.Groups[1].Value);

        // List scores in descending order.
        foreach (KeyValuePair<int, string> score in scores)
            Console.WriteLine("{0}: {1}", score.Value, score.Key);
    }
}

public class DescendingComparer<T> : IComparer<T>
{
    public int Compare(T x, T y)
    {
        return Comparer<T>.Default.Compare(x, y) * -1;
    }
}
// The example displays the following output:
//    Allison: 211
//    Sam: 208
//    Gwen: 171
//    Joe: 164
Imports System.Collections.Generic
Imports System.Text.RegularExpressions

Module Multiline2Example
    Public Sub Main()
        Dim scores As New SortedList(Of Integer, String)(New DescendingComparer(Of Integer)())

        Dim input As String = "Joe 164" + vbCrLf +
                              "Sam 208" + vbCrLf +
                              "Allison 211" + vbCrLf +
                              "Gwen 171" + vbCrLf
        Dim pattern As String = "(?m)^(\w+)\s(\d+)\r*$"

        For Each match As Match In Regex.Matches(input, pattern, RegexOptions.Multiline)
            scores.Add(CInt(match.Groups(2).Value), match.Groups(1).Value)
        Next
        ' List scores in descending order. 
        For Each score As KeyValuePair(Of Integer, String) In scores
            Console.WriteLine("{0}: {1}", score.Value, score.Key)
        Next
    End Sub
End Module

Public Class DescendingComparer(Of T) : Implements IComparer(Of T)
    Public Function Compare(x As T, y As T) As Integer _
           Implements IComparer(Of T).Compare
        Return Comparer(Of T).Default.Compare(x, y) * -1
    End Function
End Class
' The example displays the following output:
'    Allison: 211
'    Sam: 208
'    Gwen: 171
'    Joe: 164

Modo de linha única

A opção RegexOptions.Singleline, ou a opção embutida s, faz o mecanismo de expressão regular tratar a cadeia de caracteres de entrada como se consistisse em uma única linha. Ele faz isso mudando o comportamento do elemento de linguagem de ponto (.) para que corresponda a todos os caracteres, em vez de corresponder a todo caractere exceto pelo caractere de nova linha \n.

O exemplo a seguir ilustra como o comportamento do elemento de linguagem . muda quando se usa a opção RegexOptions.Singleline. A expressão regular ^.+ começa no início da cadeia de caracteres e corresponde a todos os caracteres. Por padrão, a correspondência termina no final da primeira linha; o padrão de expressão regular corresponde ao caractere de retorno de carro \r, mas não corresponde a \n. Como a opção RegexOptions.Singleline interpreta toda a cadeia de caracteres de entrada como uma única linha, ela corresponde a cada caractere na cadeia de caracteres de entrada, incluindo \n.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = "^.+";
      string input = "This is one line and" + Environment.NewLine + "this is the second.";
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine(Regex.Escape(match.Value));

      Console.WriteLine();
      foreach (Match match in Regex.Matches(input, pattern, RegexOptions.Singleline))
         Console.WriteLine(Regex.Escape(match.Value));
   }
}
// The example displays the following output:
//       This\ is\ one\ line\ and\r
//
//       This\ is\ one\ line\ and\r\nthis\ is\ the\ second\.
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "^.+"
        Dim input As String = "This is one line and" + vbCrLf + "this is the second."
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine(Regex.Escape(match.Value))
        Next
        Console.WriteLine()
        For Each match As Match In Regex.Matches(input, pattern, RegexOptions.SingleLine)
            Console.WriteLine(Regex.Escape(match.Value))
        Next
    End Sub
End Module
' The example displays the following output:
'       This\ is\ one\ line\ and\r
'       
'       This\ is\ one\ line\ and\r\nthis\ is\ the\ second\.

O exemplo a seguir é equivalente ao anterior, exceto que ele usa a opção embutida (?s) para habilitar o modo de linha única.

using System;
using System.Text.RegularExpressions;

public class SingleLineExample
{
    public static void Main()
    {
        string pattern = "(?s)^.+";
        string input = "This is one line and" + Environment.NewLine + "this is the second.";

        foreach (Match match in Regex.Matches(input, pattern))
            Console.WriteLine(Regex.Escape(match.Value));
    }
}
// The example displays the following output:
//       This\ is\ one\ line\ and\r\nthis\ is\ the\ second\.
Imports System.Text.RegularExpressions

Module SingleLineExample
    Public Sub Main()
        Dim pattern As String = "(?s)^.+"
        Dim input As String = "This is one line and" + vbCrLf + "this is the second."

        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine(Regex.Escape(match.Value))
        Next
    End Sub
End Module
' The example displays the following output:
'       This\ is\ one\ line\ and\r\nthis\ is\ the\ second\.

Apenas capturas explícitas

Por padrão, grupos de capturas são definidos pelo uso de parênteses no padrão de expressão regular. Grupos nomeados recebem um nome ou número pela opção de linguagem (?<nome>subexpressão), enquanto grupos não nomeados são acessíveis pelo índice. No objeto GroupCollection, grupos não nomeados precedem grupos nomeados.

Constructos de agrupamento costumam ser usados apenas para aplicar quantificadores a vários elementos de linguagem; as subcadeias de caracteres capturadas não são de interesse. Por exemplo, se a seguinte expressão regular:

\b\(?((\w+),?\s?)+[\.!?]\)?

for feita somente para extrair frases que terminem com um ponto, ponto de exclamação ou ponto de interrogação de um documento, apenas a frase resultante (representada pelo objeto Match) é de interesse. As palavras individuais na coleção não são.

Capturar grupos que não serão usados posteriormente pode ser caro, pois o mecanismo de expressão regular precisa preencher os objetos de coleção GroupCollection e CaptureCollection. Como alternativa, você pode usar a opção RegexOptions.ExplicitCapture ou a opção embutida n para especificar que apenas as capturas válidas são explicitamente nomeadas ou grupos numerados que são projetados pelo constructo (?<nome>subexpressão).

O exemplo a seguir exibe informações sobre as correspondências retornadas pelo padrão de expressão regular \b\(?((\w+),?\s?)+[\.!?]\)? quando o método Match é chamado com e sem a opção RegexOptions.ExplicitCapture. Como mostra a saída da chamada do primeiro método, o mecanismo de expressão regular preenche totalmente os objetos da coleção GroupCollection e CaptureCollection com informações sobre subcadeias de caracteres capturadas. Como o segundo método é chamado com options definido para RegexOptions.ExplicitCapture, ele não captura informações sobre grupos.

using System;
using System.Text.RegularExpressions;

public class Explicit1Example
{
    public static void Main()
    {
        string input = "This is the first sentence. Is it the beginning " +
                       "of a literary masterpiece? I think not. Instead, " +
                       "it is a nonsensical paragraph.";
        string pattern = @"\b\(?((?>\w+),?\s?)+[\.!?]\)?";
        Console.WriteLine("With implicit captures:");
        foreach (Match match in Regex.Matches(input, pattern))
        {
            Console.WriteLine("The match: {0}", match.Value);
            int groupCtr = 0;
            foreach (Group group in match.Groups)
            {
                Console.WriteLine("   Group {0}: {1}", groupCtr, group.Value);
                groupCtr++;
                int captureCtr = 0;
                foreach (Capture capture in group.Captures)
                {
                    Console.WriteLine("      Capture {0}: {1}", captureCtr, capture.Value);
                    captureCtr++;
                }
            }
        }
        Console.WriteLine();
        Console.WriteLine("With explicit captures only:");
        foreach (Match match in Regex.Matches(input, pattern, RegexOptions.ExplicitCapture))
        {
            Console.WriteLine("The match: {0}", match.Value);
            int groupCtr = 0;
            foreach (Group group in match.Groups)
            {
                Console.WriteLine("   Group {0}: {1}", groupCtr, group.Value);
                groupCtr++;
                int captureCtr = 0;
                foreach (Capture capture in group.Captures)
                {
                    Console.WriteLine("      Capture {0}: {1}", captureCtr, capture.Value);
                    captureCtr++;
                }
            }
        }
    }
}
// The example displays the following output:
//    With implicit captures:
//    The match: This is the first sentence.
//       Group 0: This is the first sentence.
//          Capture 0: This is the first sentence.
//       Group 1: sentence
//          Capture 0: This
//          Capture 1: is
//          Capture 2: the
//          Capture 3: first
//          Capture 4: sentence
//       Group 2: sentence
//          Capture 0: This
//          Capture 1: is
//          Capture 2: the
//          Capture 3: first
//          Capture 4: sentence
//    The match: Is it the beginning of a literary masterpiece?
//       Group 0: Is it the beginning of a literary masterpiece?
//          Capture 0: Is it the beginning of a literary masterpiece?
//       Group 1: masterpiece
//          Capture 0: Is
//          Capture 1: it
//          Capture 2: the
//          Capture 3: beginning
//          Capture 4: of
//          Capture 5: a
//          Capture 6: literary
//          Capture 7: masterpiece
//       Group 2: masterpiece
//          Capture 0: Is
//          Capture 1: it
//          Capture 2: the
//          Capture 3: beginning
//          Capture 4: of
//          Capture 5: a
//          Capture 6: literary
//          Capture 7: masterpiece
//    The match: I think not.
//       Group 0: I think not.
//          Capture 0: I think not.
//       Group 1: not
//          Capture 0: I
//          Capture 1: think
//          Capture 2: not
//       Group 2: not
//          Capture 0: I
//          Capture 1: think
//          Capture 2: not
//    The match: Instead, it is a nonsensical paragraph.
//       Group 0: Instead, it is a nonsensical paragraph.
//          Capture 0: Instead, it is a nonsensical paragraph.
//       Group 1: paragraph
//          Capture 0: Instead,
//          Capture 1: it
//          Capture 2: is
//          Capture 3: a
//          Capture 4: nonsensical
//          Capture 5: paragraph
//       Group 2: paragraph
//          Capture 0: Instead
//          Capture 1: it
//          Capture 2: is
//          Capture 3: a
//          Capture 4: nonsensical
//          Capture 5: paragraph
//
//    With explicit captures only:
//    The match: This is the first sentence.
//       Group 0: This is the first sentence.
//          Capture 0: This is the first sentence.
//    The match: Is it the beginning of a literary masterpiece?
//       Group 0: Is it the beginning of a literary masterpiece?
//          Capture 0: Is it the beginning of a literary masterpiece?
//    The match: I think not.
//       Group 0: I think not.
//          Capture 0: I think not.
//    The match: Instead, it is a nonsensical paragraph.
//       Group 0: Instead, it is a nonsensical paragraph.
//          Capture 0: Instead, it is a nonsensical paragraph.
Imports System.Text.RegularExpressions

Module Explicit1Example
    Public Sub Main()
        Dim input As String = "This is the first sentence. Is it the beginning " +
                              "of a literary masterpiece? I think not. Instead, " +
                              "it is a nonsensical paragraph."
        Dim pattern As String = "\b\(?((?>\w+),?\s?)+[\.!?]\)?"
        Console.WriteLine("With implicit captures:")
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("The match: {0}", match.Value)
            Dim groupCtr As Integer = 0
            For Each group As Group In match.Groups
                Console.WriteLine("   Group {0}: {1}", groupCtr, group.Value)
                groupCtr += 1
                Dim captureCtr As Integer = 0
                For Each capture As Capture In group.Captures
                    Console.WriteLine("      Capture {0}: {1}", captureCtr, capture.Value)
                    captureCtr += 1
                Next
            Next
        Next
        Console.WriteLine()
        Console.WriteLine("With explicit captures only:")
        For Each match As Match In Regex.Matches(input, pattern, RegexOptions.ExplicitCapture)
            Console.WriteLine("The match: {0}", match.Value)
            Dim groupCtr As Integer = 0
            For Each group As Group In match.Groups
                Console.WriteLine("   Group {0}: {1}", groupCtr, group.Value)
                groupCtr += 1
                Dim captureCtr As Integer = 0
                For Each capture As Capture In group.Captures
                    Console.WriteLine("      Capture {0}: {1}", captureCtr, capture.Value)
                    captureCtr += 1
                Next
            Next
        Next
    End Sub
End Module
' The example displays the following output:
'    With implicit captures:
'    The match: This is the first sentence.
'       Group 0: This is the first sentence.
'          Capture 0: This is the first sentence.
'       Group 1: sentence
'          Capture 0: This
'          Capture 1: is
'          Capture 2: the
'          Capture 3: first
'          Capture 4: sentence
'       Group 2: sentence
'          Capture 0: This
'          Capture 1: is
'          Capture 2: the
'          Capture 3: first
'          Capture 4: sentence
'    The match: Is it the beginning of a literary masterpiece?
'       Group 0: Is it the beginning of a literary masterpiece?
'          Capture 0: Is it the beginning of a literary masterpiece?
'       Group 1: masterpiece
'          Capture 0: Is
'          Capture 1: it
'          Capture 2: the
'          Capture 3: beginning
'          Capture 4: of
'          Capture 5: a
'          Capture 6: literary
'          Capture 7: masterpiece
'       Group 2: masterpiece
'          Capture 0: Is
'          Capture 1: it
'          Capture 2: the
'          Capture 3: beginning
'          Capture 4: of
'          Capture 5: a
'          Capture 6: literary
'          Capture 7: masterpiece
'    The match: I think not.
'       Group 0: I think not.
'          Capture 0: I think not.
'       Group 1: not
'          Capture 0: I
'          Capture 1: think
'          Capture 2: not
'       Group 2: not
'          Capture 0: I
'          Capture 1: think
'          Capture 2: not
'    The match: Instead, it is a nonsensical paragraph.
'       Group 0: Instead, it is a nonsensical paragraph.
'          Capture 0: Instead, it is a nonsensical paragraph.
'       Group 1: paragraph
'          Capture 0: Instead,
'          Capture 1: it
'          Capture 2: is
'          Capture 3: a
'          Capture 4: nonsensical
'          Capture 5: paragraph
'       Group 2: paragraph
'          Capture 0: Instead
'          Capture 1: it
'          Capture 2: is
'          Capture 3: a
'          Capture 4: nonsensical
'          Capture 5: paragraph
'    
'    With explicit captures only:
'    The match: This is the first sentence.
'       Group 0: This is the first sentence.
'          Capture 0: This is the first sentence.
'    The match: Is it the beginning of a literary masterpiece?
'       Group 0: Is it the beginning of a literary masterpiece?
'          Capture 0: Is it the beginning of a literary masterpiece?
'    The match: I think not.
'       Group 0: I think not.
'          Capture 0: I think not.
'    The match: Instead, it is a nonsensical paragraph.
'       Group 0: Instead, it is a nonsensical paragraph.
'          Capture 0: Instead, it is a nonsensical paragraph.

O padrão de expressão regular\b\(?((?>\w+),?\s?)+[\.!?]\)? é definido como mostra a tabela a seguir.

Padrão Descrição
\b Começar em um limite de palavra.
\(? Corresponder zero ou uma ocorrência do parêntese de abertura (“(“).
(?>\w+),? Corresponder um ou mais caracteres de palavra seguidos por zero ou uma vírgula. Não retroceda ao corresponder caracteres de palavra.
\s? Corresponder a zero ou a um caractere de espaço em branco.
((\w+),?\s?)+ Corresponder a combinação de um ou mais caracteres de palavra, zero ou mais vírgulas e zero ou um caractere de espaço em branco uma ou mais vezes.
[\.!?]\)? Corresponder qualquer um dos três símbolos de pontuação seguidos por zero ou um parêntese de fechamento (“)”).

Você também pode usar o elemento embutido (?n) para suprimir capturas automáticas. O exemplo a seguir modifica o padrão de expressão regular anterior para usar o elemento embutido (?n) em vez da opção RegexOptions.ExplicitCapture.

using System;
using System.Text.RegularExpressions;

public class Explicit2Example
{
    public static void Main()
    {
        string input = "This is the first sentence. Is it the beginning " +
                       "of a literary masterpiece? I think not. Instead, " +
                       "it is a nonsensical paragraph.";
        string pattern = @"(?n)\b\(?((?>\w+),?\s?)+[\.!?]\)?";

        foreach (Match match in Regex.Matches(input, pattern))
        {
            Console.WriteLine("The match: {0}", match.Value);
            int groupCtr = 0;
            foreach (Group group in match.Groups)
            {
                Console.WriteLine("   Group {0}: {1}", groupCtr, group.Value);
                groupCtr++;
                int captureCtr = 0;
                foreach (Capture capture in group.Captures)
                {
                    Console.WriteLine("      Capture {0}: {1}", captureCtr, capture.Value);
                    captureCtr++;
                }
            }
        }
    }
}
// The example displays the following output:
//       The match: This is the first sentence.
//          Group 0: This is the first sentence.
//             Capture 0: This is the first sentence.
//       The match: Is it the beginning of a literary masterpiece?
//          Group 0: Is it the beginning of a literary masterpiece?
//             Capture 0: Is it the beginning of a literary masterpiece?
//       The match: I think not.
//          Group 0: I think not.
//             Capture 0: I think not.
//       The match: Instead, it is a nonsensical paragraph.
//          Group 0: Instead, it is a nonsensical paragraph.
//             Capture 0: Instead, it is a nonsensical paragraph.
Imports System.Text.RegularExpressions

Module Explicit2Example
    Public Sub Main()
        Dim input As String = "This is the first sentence. Is it the beginning " +
                              "of a literary masterpiece? I think not. Instead, " +
                              "it is a nonsensical paragraph."
        Dim pattern As String = "(?n)\b\(?((?>\w+),?\s?)+[\.!?]\)?"

        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("The match: {0}", match.Value)
            Dim groupCtr As Integer = 0
            For Each group As Group In match.Groups
                Console.WriteLine("   Group {0}: {1}", groupCtr, group.Value)
                groupCtr += 1
                Dim captureCtr As Integer = 0
                For Each capture As Capture In group.Captures
                    Console.WriteLine("      Capture {0}: {1}", captureCtr, capture.Value)
                    captureCtr += 1
                Next
            Next
        Next
    End Sub
End Module
' The example displays the following output:
'       The match: This is the first sentence.
'          Group 0: This is the first sentence.
'             Capture 0: This is the first sentence.
'       The match: Is it the beginning of a literary masterpiece?
'          Group 0: Is it the beginning of a literary masterpiece?
'             Capture 0: Is it the beginning of a literary masterpiece?
'       The match: I think not.
'          Group 0: I think not.
'             Capture 0: I think not.
'       The match: Instead, it is a nonsensical paragraph.
'          Group 0: Instead, it is a nonsensical paragraph.
'             Capture 0: Instead, it is a nonsensical paragraph.

Por fim, é possível usar o elemento do grupo embutido (?n:) para suprimir capturas automáticas grupo a grupo. O exemplo a seguir modifica o padrão anterior para suprimir capturas sem nome no grupo externo, ((?>\w+),?\s?). Observe que isso também suprime capturas sem nome no grupo interno.

using System;
using System.Text.RegularExpressions;

public class Explicit3Example
{
    public static void Main()
    {
        string input = "This is the first sentence. Is it the beginning " +
                       "of a literary masterpiece? I think not. Instead, " +
                       "it is a nonsensical paragraph.";
        string pattern = @"\b\(?(?n:(?>\w+),?\s?)+[\.!?]\)?";

        foreach (Match match in Regex.Matches(input, pattern))
        {
            Console.WriteLine("The match: {0}", match.Value);
            int groupCtr = 0;
            foreach (Group group in match.Groups)
            {
                Console.WriteLine("   Group {0}: {1}", groupCtr, group.Value);
                groupCtr++;
                int captureCtr = 0;
                foreach (Capture capture in group.Captures)
                {
                    Console.WriteLine("      Capture {0}: {1}", captureCtr, capture.Value);
                    captureCtr++;
                }
            }
        }
    }
}
// The example displays the following output:
//       The match: This is the first sentence.
//          Group 0: This is the first sentence.
//             Capture 0: This is the first sentence.
//       The match: Is it the beginning of a literary masterpiece?
//          Group 0: Is it the beginning of a literary masterpiece?
//             Capture 0: Is it the beginning of a literary masterpiece?
//       The match: I think not.
//          Group 0: I think not.
//             Capture 0: I think not.
//       The match: Instead, it is a nonsensical paragraph.
//          Group 0: Instead, it is a nonsensical paragraph.
//             Capture 0: Instead, it is a nonsensical paragraph.
Imports System.Text.RegularExpressions

Module Explicit3Example
    Public Sub Main()
        Dim input As String = "This is the first sentence. Is it the beginning " +
                              "of a literary masterpiece? I think not. Instead, " +
                              "it is a nonsensical paragraph."
        Dim pattern As String = "\b\(?(?n:(?>\w+),?\s?)+[\.!?]\)?"

        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("The match: {0}", match.Value)
            Dim groupCtr As Integer = 0
            For Each group As Group In match.Groups
                Console.WriteLine("   Group {0}: {1}", groupCtr, group.Value)
                groupCtr += 1
                Dim captureCtr As Integer = 0
                For Each capture As Capture In group.Captures
                    Console.WriteLine("      Capture {0}: {1}", captureCtr, capture.Value)
                    captureCtr += 1
                Next
            Next
        Next
    End Sub
End Module
' The example displays the following output:
'       The match: This is the first sentence.
'          Group 0: This is the first sentence.
'             Capture 0: This is the first sentence.
'       The match: Is it the beginning of a literary masterpiece?
'          Group 0: Is it the beginning of a literary masterpiece?
'             Capture 0: Is it the beginning of a literary masterpiece?
'       The match: I think not.
'          Group 0: I think not.
'             Capture 0: I think not.
'       The match: Instead, it is a nonsensical paragraph.
'          Group 0: Instead, it is a nonsensical paragraph.
'             Capture 0: Instead, it is a nonsensical paragraph.

Expressões regulares compiladas

Observação

Sempre que possível, use expressões regulares geradas pela origem em vez de compilar expressões regulares usando a opção RegexOptions.Compiled. A geração de origem pode ajudar seu aplicativo a iniciar com mais rapidez, ser executado com mais agilidade e ser mais completo. Para saber quando a geração de origem é possível, confira Quando usá-la.

Por padrão, as expressões regulares no .NET são interpretadas. Quando um objeto Regex é instanciado ou um método Regex estático é chamado, o padrão de expressão regular é analisado em um conjunto de opcodes personalizados, e um interpretador usa esses opcodes para executar a expressão regular. Isso envolve uma troca: o custo de inicializar o mecanismo de expressões regulares é minimizado com prejuízo do desempenho do tempo de execução.

Você pode usar expressões regulares compiladas, em vez de interpretadas, usando a opção RegexOptions.Compiled. Neste caso, quando um padrão é enviado ao mecanismo de expressões regulares, ele é analisado em um subconjunto de opcodes e convertido para a MSIL (linguagem intermediária da Microsoft), que pode ser enviada diretamente ao Common Language Runtime. Expressões regulares compiladas maximizam o desempenho do tempo de execução às custas do tempo de inicialização.

Observação

Uma expressão regular só pode ser compilada fornecendo o valor RegexOptions.Compiled ao parâmetro options de um construtor de classe Regex ou um método de correspondência padrão estático. Não está disponível como uma opção embutida.

É possível usar expressões regulares compiladas em chamadas para expressões regulares estáticas e de instância. Em expressões regulares estáticas, a opção RegexOptions.Compiled é enviada ao parâmetro options do método de correspondência padrão de expressão regular. Em expressões regulares de instância, é enviado ao parâmetro options do construtor de classe Regex. Em ambos os casos, resulta em melhoria de desempenho.

Porém, essa melhoria de desempenho ocorre apenas sob as seguintes condições:

  • É usado um objeto Regex que representa uma expressão regular em particular, em várias chamadas para métodos de correspondência padrão de expressão regular.

  • O objeto Regex não pode sair do escopo, então pode ser reutilizado.

  • Uma expressão regular estática é usada em várias chamadas para métodos de correspondência padrão de expressão regular. (A melhoria de desempenho é possível porque as expressões regulares usadas em chamadas de método estático são armazenadas em cache pelo mecanismo de expressões regulares.)

Observação

A opção RegexOptions.Compiled não está relacionada ao método Regex.CompileToAssembly, que cria um assembly de uso especial contendo expressões regulares compiladas predefinidas.

Ignorar espaço em branco

Por padrão, o espaço em branco em um padrão de expressão regular é significativo; ele força o mecanismo de expressões regulares para combinar um caractere de espaço em branco na cadeia de caracteres de entrada. Devido a isso, a expressão regular "\b\w+\s" e "\b\w+" são, de um modo geral, equivalentes. Além disso, quando a tecla de cerquilha (#) é encontrada em um padrão de expressão regular, ela é interpretada como um caractere literal a ser combinado.

A opção RegexOptions.IgnorePatternWhitespace ou a opção embutida x muda seu comportamento padrão da seguinte maneira:

  • É ignorado o espaço em branco sem escape no padrão de expressão regular. Para fazer parte de um padrão de expressão regular, os caracteres de espaço em branco devem ser escapados (por exemplo, \s ou "\").

  • A tecla de cerquilha (#) é interpretada como o início de um comentário, em vez de um caractere literal. Todo o texto no padrão de expressão regular do caractere # até o próximo caractere \n ou até o fim da cadeia de caracteres é interpretado como comentário.

No entanto, nos casos a seguir, os caracteres de espaço em branco em uma expressão regular não serão ignorados, mesmo se você usar a opção RegexOptions.IgnorePatternWhitespace:

  • O espaço em branco dentro de uma classe de caractere sempre é interpretado literalmente. Por exemplo, o padrão da expressão regular [ .,;:] corresponde a qualquer caractere de espaço em branco, ponto, vírgula, dois pontos ou ponto e vírgula único.

  • O espaço em branco não é permitido dentro de um quantificador entre colchetes, como {n}, {n,} e {n,m}. Por exemplo, o padrão de expressão regular \d{1, 3} falha ao corresponder quaisquer sequências de dígitos de um a três dígitos porque contém um caractere de espaço em branco.

  • Não é permitido espaço em branco dentro da sequência de caracteres que introduz um elemento de linguagem. Por exemplo:

    • O elemento de linguagem (?:subexpressão) representa um grupo sem captura; a parte (?: do elemento não pode ter espaços inseridos. O padrão (? :subexpressão) lança uma ArgumentException no tempo de execução porque o mecanismo de expressão regular não consegue analisar o padrão, e o padrão ( ?:subexpressão) falha em corresponder a subexpressão.

    • O elemento de linguagem \p{name}, que representa uma categoria Unicode ou um bloco nomeado, não pode incluir espaços inseridos na parte \p{ do elemento. Se você incluir um espaço em branco, o elemento lança uma ArgumentException no tempo de execução.

Habilitar essa opção ajuda a simplificar expressões regulares que costumam ser difíceis de analisar e entender. Melhora a legibilidade e torna possível documentar uma expressão regular.

O exemplo a seguir define o padrão de expressão regular a seguir:

\b \(? ( (?>\w+) ,?\s? )+ [\.!?] \)? # Matches an entire sentence.

Esse padrão é similar ao padrão definido na seção Apenas capturas explícitas, exceto por usar a opção RegexOptions.IgnorePatternWhitespace para ignorar espaço em branco de padrão.

using System;
using System.Text.RegularExpressions;

public class Whitespace1Example
{
    public static void Main()
    {
        string input = "This is the first sentence. Is it the beginning " +
                       "of a literary masterpiece? I think not. Instead, " +
                       "it is a nonsensical paragraph.";
        string pattern = @"\b \(? ( (?>\w+) ,?\s? )+ [\.!?] \)? # Matches an entire sentence.";

        foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnorePatternWhitespace))
            Console.WriteLine(match.Value);
    }
}
// The example displays the following output:
//       This is the first sentence.
//       Is it the beginning of a literary masterpiece?
//       I think not.
//       Instead, it is a nonsensical paragraph.
Imports System.Text.RegularExpressions

Module Whitespace1Example
    Public Sub Main()
        Dim input As String = "This is the first sentence. Is it the beginning " +
                              "of a literary masterpiece? I think not. Instead, " +
                              "it is a nonsensical paragraph."
        Dim pattern As String = "\b \(? ( (?>\w+) ,?\s? )+  [\.!?] \)? # Matches an entire sentence."

        For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnorePatternWhitespace)
            Console.WriteLine(match.Value)
        Next
    End Sub
End Module
' The example displays the following output:
'       This is the first sentence.
'       Is it the beginning of a literary masterpiece?
'       I think not.
'       Instead, it is a nonsensical paragraph.

O exemplo a seguir usa a opção embutida (?x) para ignorar o espaço em branco padrão.

using System;
using System.Text.RegularExpressions;

public class Whitespace2Example
{
    public static void Main()
    {
        string input = "This is the first sentence. Is it the beginning " +
                       "of a literary masterpiece? I think not. Instead, " +
                       "it is a nonsensical paragraph.";
        string pattern = @"(?x)\b \(? ( (?>\w+) ,?\s? )+  [\.!?] \)? # Matches an entire sentence.";

        foreach (Match match in Regex.Matches(input, pattern))
            Console.WriteLine(match.Value);
    }
}
// The example displays the following output:
//       This is the first sentence.
//       Is it the beginning of a literary masterpiece?
//       I think not.
//       Instead, it is a nonsensical paragraph.
Imports System.Text.RegularExpressions

Module Whitespace2Example
    Public Sub Main()
        Dim input As String = "This is the first sentence. Is it the beginning " +
                              "of a literary masterpiece? I think not. Instead, " +
                              "it is a nonsensical paragraph."
        Dim pattern As String = "(?x)\b \(? ( (?>\w+) ,?\s? )+  [\.!?] \)? # Matches an entire sentence."

        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine(match.Value)
        Next
    End Sub
End Module
' The example displays the following output:
'       This is the first sentence.
'       Is it the beginning of a literary masterpiece?
'       I think not.
'       Instead, it is a nonsensical paragraph.

Modo da direita para a esquerda

Por padrão, o mecanismo de expressões regulares pesquisa da esquerda para a direita. É possível reverter a direção de pesquisa usando a opção RegexOptions.RightToLeft. A pesquisa da direita para esquerda inicia automaticamente na última posição de caractere da cadeia de caracteres. Para métodos de correspondência padrão que incluem um parâmetro de posição inicial, como Regex.Match(String, Int32), a posição inicial especificada é o índice da posição do caractere mais à direita em que a pesquisa deve iniciar.

Observação

O modo de padrão da direita para a esquerda está disponível apenas fornecendo o valor RegexOptions.RightToLeft para o parâmetro options de um construtor de classe Regex ou o método de correspondência padrão estático. Não está disponível como uma opção embutida.

Exemplo

A expressão regular \bb\w+\s corresponde palavras com dois ou mais caracteres que começam com a letra “b” e são seguidas por um caractere de espaço em branco. No exemplo a seguir, a cadeia de caracteres de entrada consiste em três palavras que incluem um ou mais caracteres “b”. A primeira e a segunda palavras começam com "b", e a terceira palavra termina com "b". Como mostra a saída do exemplo de pesquisa da direita para a esquerda, apenas a primeira e a segunda palavras correspondem ao padrão de expressão regular, com a segunda palavra sendo correspondida primeiro.

using System;
using System.Text.RegularExpressions;

public class RTL1Example
{
    public static void Main()
    {
        string pattern = @"\bb\w+\s";
        string input = "build band tab";
        foreach (Match match in Regex.Matches(input, pattern, RegexOptions.RightToLeft))
            Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index);
    }
}
// The example displays the following output:
//       'band ' found at position 6.
//       'build ' found at position 0.
Imports System.Text.RegularExpressions

Module RTL1Example
    Public Sub Main()
        Dim pattern As String = "\bb\w+\s"
        Dim input As String = "build band tab"
        For Each match As Match In Regex.Matches(input, pattern, RegexOptions.RightToLeft)
            Console.WriteLine("'{0}' found at position {1}.", match.Value, match.Index)
        Next
    End Sub
End Module
' The example displays the following output:
'       'band ' found at position 6.
'       'build ' found at position 0.

Ordem de avaliação

A opção RegexOptions.RightToLeft altera a direção da pesquisa e também inverte a ordem na qual o padrão de expressão regular é avaliado. Em uma pesquisa da direita para a esquerda, o padrão de pesquisa é lido da direita para a esquerda. Essa distinção é importante porque pode afetar coisas como grupos de captura e referências inversas. Por exemplo, a expressão Regex.Match("abcabc", @"\1(abc)", RegexOptions.RightToLeft) encontra uma correspondência abcabc, mas em uma pesquisa da esquerda para a direita (Regex.Match("abcabc", @"\1(abc)", RegexOptions.None)), nenhuma correspondência é encontrada. Isso ocorre porque o elemento (abc) deve ser avaliado antes do elemento de grupo de captura numerado (\1) para que uma correspondência seja encontrada.

Asserções lookbehind e lookahead

O local de uma correspondência para uma asserção lookahead ((?=subexpression)) ou lookbehind ((?<=subexpression)) não muda em uma pesquisa da direita para a esquerda. As asserções lookahead olham para a direita do local da correspondência atual; as asserções lookbehind olham para a esquerda do local da correspondência atual.

Dica

Se uma pesquisa é da direita para a esquerda ou não, os lookbehinds são implementados usando uma pesquisa da direita para a esquerda começando no local da correspondência atual.

Por exemplo, a expressão regular (?<=\d{1,2}\s)\w+,\s\d{4} usa a asserção lookbehind para testar uma data que antecede um nome de mês. A expressão regular corresponde ao mês e o ano. Saiba mais sobre as asserções lookahead e lookbehind em Constructos de agrupamento.

using System;
using System.Text.RegularExpressions;

public class RTL2Example
{
    public static void Main()
    {
        string[] inputs = { "1 May, 1917", "June 16, 2003" };
        string pattern = @"(?<=\d{1,2}\s)\w+,\s\d{4}";

        foreach (string input in inputs)
        {
            Match match = Regex.Match(input, pattern, RegexOptions.RightToLeft);
            if (match.Success)
                Console.WriteLine("The date occurs in {0}.", match.Value);
            else
                Console.WriteLine("{0} does not match.", input);
        }
    }
}

// The example displays the following output:
//       The date occurs in May, 1917.
//       June 16, 2003 does not match.
Imports System.Text.RegularExpressions

Module RTL2Example
    Public Sub Main()
        Dim inputs() As String = {"1 May, 1917", "June 16, 2003"}
        Dim pattern As String = "(?<=\d{1,2}\s)\w+,\s\d{4}"

        For Each input As String In inputs
            Dim match As Match = Regex.Match(input, pattern, RegexOptions.RightToLeft)
            If match.Success Then
                Console.WriteLine("The date occurs in {0}.", match.Value)
            Else
                Console.WriteLine("{0} does not match.", input)
            End If
        Next
    End Sub
End Module

' The example displays the following output:
'       The date occurs in May, 1917.
'       June 16, 2003 does not match.

O padrão de expressão regular é definido como mostra a tabela a seguir.

Padrão Descrição
(?<=\d{1,2}\s) O início da correspondência deve ser antecedido por um ou dois dígitos decimais seguidos por um espaço.
\w+ Fazer a correspondência a um ou mais caracteres de palavra.
, Corresponda um caractere de vírgula.
\s Corresponde a um caractere de espaço em branco.
\d{4} Corresponder a quatro dígitos decimais.

Comportamento de correspondência de ECMAScript

Por padrão, o mecanismo de expressões regulares usa comportamento canônico ao corresponder um padrão de expressão regular a um texto de entrada. Porém, é possível instruir o mecanismo de expressão regular a usar o comportamento de correspondência ECMAScript especificando a opção RegexOptions.ECMAScript.

Observação

O comportamento compatível com ECMAScript está disponível apenas fornecendo o valor RegexOptions.ECMAScript para o parâmetro options de um construtor de classe Regex ou método de correspondência padrão estático. Não está disponível como uma opção embutida.

A opção RegexOptions.ECMAScript só pode ser combinada com as opções RegexOptions.IgnoreCase e RegexOptions.Multiline. O uso de qualquer outra opção em uma expressão regular resulta em ArgumentOutOfRangeException.

O comportamento das expressões regulares ECMAScript e canônicas difere em três áreas: sintaxe da classe de caractere, grupos de captura autorreferidos e interpretação octal versus de referência inversa.

  • Sintaxe da classe de caractere. Como as expressões regulares canônicas dão suporte a Unicode e o ECMAScrip não, as classes de caractere no ECMAScrip têm uma sintaxe mais limitada e alguns elementos de linguagem da classe de caractere têm um significado diferente. Por exemplo, o ECMAScript não oferece suporte a elementos de linguagem como a categoria Unicode ou elementos de bloco \p e \P. De modo similar, o elemento \w, que corresponde um caractere de palavra, é equivalente à classe de caractere [a-zA-Z_0-9] ao usar ECMAScript e [\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}\p{Pc}\p{Lm}] ao usar comportamento canônico. Para saber mais, confira Classes de caracteres.

    O exemplo a seguir ilustra a diferença entre correspondência padrão ECMAScript e canônica. Define uma expressão regular, \b(\w+\s*)+, que combina palavras seguidas por caracteres de espaço em branco. A entrada consiste em duas cadeias de caracteres, uma que usa o conjunto de caracteres latinos e outra que usa o conjunto de caracteres cirílicos. Como a saída mostra, a chamada para o método Regex.IsMatch(String, String, RegexOptions) que usa correspondência ECMAScript falha ao combinar as palavras cirílicas, enquanto a chamada de método que usa correspondência canônica não corresponde essas palavras.

    using System;
    using System.Text.RegularExpressions;
    
    public class EcmaScriptExample
    {
        public static void Main()
        {
            string[] values = { "целый мир", "the whole world" };
            string pattern = @"\b(\w+\s*)+";
            foreach (var value in values)
            {
                Console.Write("Canonical matching: ");
                if (Regex.IsMatch(value, pattern))
                    Console.WriteLine("'{0}' matches the pattern.", value);
                else
                    Console.WriteLine("{0} does not match the pattern.", value);
    
                Console.Write("ECMAScript matching: ");
                if (Regex.IsMatch(value, pattern, RegexOptions.ECMAScript))
                    Console.WriteLine("'{0}' matches the pattern.", value);
                else
                    Console.WriteLine("{0} does not match the pattern.", value);
                Console.WriteLine();
            }
        }
    }
    // The example displays the following output:
    //       Canonical matching: 'целый мир' matches the pattern.
    //       ECMAScript matching: целый мир does not match the pattern.
    //
    //       Canonical matching: 'the whole world' matches the pattern.
    //       ECMAScript matching: 'the whole world' matches the pattern.
    
    Imports System.Text.RegularExpressions
    
    Module Ecma1Example
        Public Sub Main()
            Dim values() As String = {"целый мир", "the whole world"}
            Dim pattern As String = "\b(\w+\s*)+"
            For Each value In values
                Console.Write("Canonical matching: ")
                If Regex.IsMatch(value, pattern) Then
                    Console.WriteLine("'{0}' matches the pattern.", value)
                Else
                    Console.WriteLine("{0} does not match the pattern.", value)
                End If
    
                Console.Write("ECMAScript matching: ")
                If Regex.IsMatch(value, pattern, RegexOptions.ECMAScript) Then
                    Console.WriteLine("'{0}' matches the pattern.", value)
                Else
                    Console.WriteLine("{0} does not match the pattern.", value)
                End If
                Console.WriteLine()
            Next
        End Sub
    End Module
    ' The example displays the following output:
    '       Canonical matching: 'целый мир' matches the pattern.
    '       ECMAScript matching: целый мир does not match the pattern.
    '       
    '       Canonical matching: 'the whole world' matches the pattern.
    '       ECMAScript matching: 'the whole world' matches the pattern.
    
  • Grupos de capturas com autorreferência. Uma classe de captura de expressão regular com uma referência inversa para si mesma deve ser atualizada com cada iteração de captura. Como o exemplo a seguir mostra, esse recurso habilita a expressão regular ((a+)(\1) ?)+ para corresponder a cadeia de caracteres de entrada “ aa aaaa aaaaaa ” ao usar ECMAScript, mas não ao usar correspondência canônica.

    using System;
    using System.Text.RegularExpressions;
    
    public class EcmaScript2Example
    {
        static string pattern;
    
        public static void Main()
        {
            string input = "aa aaaa aaaaaa ";
            pattern = @"((a+)(\1) ?)+";
    
            // Match input using canonical matching.
            AnalyzeMatch(Regex.Match(input, pattern));
    
            // Match input using ECMAScript.
            AnalyzeMatch(Regex.Match(input, pattern, RegexOptions.ECMAScript));
        }
    
        private static void AnalyzeMatch(Match m)
        {
            if (m.Success)
            {
                Console.WriteLine("'{0}' matches {1} at position {2}.",
                                  pattern, m.Value, m.Index);
                int grpCtr = 0;
                foreach (Group grp in m.Groups)
                {
                    Console.WriteLine("   {0}: '{1}'", grpCtr, grp.Value);
                    grpCtr++;
                    int capCtr = 0;
                    foreach (Capture cap in grp.Captures)
                    {
                        Console.WriteLine("      {0}: '{1}'", capCtr, cap.Value);
                        capCtr++;
                    }
                }
            }
            else
            {
                Console.WriteLine("No match found.");
            }
            Console.WriteLine();
        }
    }
    // The example displays the following output:
    //    No match found.
    //
    //    '((a+)(\1) ?)+' matches aa aaaa aaaaaa  at position 0.
    //       0: 'aa aaaa aaaaaa '
    //          0: 'aa aaaa aaaaaa '
    //       1: 'aaaaaa '
    //          0: 'aa '
    //          1: 'aaaa '
    //          2: 'aaaaaa '
    //       2: 'aa'
    //          0: 'aa'
    //          1: 'aa'
    //          2: 'aa'
    //       3: 'aaaa '
    //          0: ''
    //          1: 'aa '
    //          2: 'aaaa '
    
    Imports System.Text.RegularExpressions
    
    Module Ecma2Example
        Dim pattern As String
    
        Public Sub Main()
            Dim input As String = "aa aaaa aaaaaa "
            pattern = "((a+)(\1) ?)+"
    
            ' Match input using canonical matching.
            AnalyzeMatch(Regex.Match(input, pattern))
    
            ' Match input using ECMAScript.
            AnalyzeMatch(Regex.Match(input, pattern, RegexOptions.ECMAScript))
        End Sub
    
        Private Sub AnalyzeMatch(m As Match)
            If m.Success Then
                Console.WriteLine("'{0}' matches {1} at position {2}.",
                                  pattern, m.Value, m.Index)
                Dim grpCtr As Integer = 0
                For Each grp As Group In m.Groups
                    Console.WriteLine("   {0}: '{1}'", grpCtr, grp.Value)
                    grpCtr += 1
                    Dim capCtr As Integer = 0
                    For Each cap As Capture In grp.Captures
                        Console.WriteLine("      {0}: '{1}'", capCtr, cap.Value)
                        capCtr += 1
                    Next
                Next
            Else
                Console.WriteLine("No match found.")
            End If
            Console.WriteLine()
        End Sub
    End Module
    ' The example displays the following output:
    '    No match found.
    '    
    '    '((a+)(\1) ?)+' matches aa aaaa aaaaaa  at position 0.
    '       0: 'aa aaaa aaaaaa '
    '          0: 'aa aaaa aaaaaa '
    '       1: 'aaaaaa '
    '          0: 'aa '
    '          1: 'aaaa '
    '          2: 'aaaaaa '
    '       2: 'aa'
    '          0: 'aa'
    '          1: 'aa'
    '          2: 'aa'
    '       3: 'aaaa '
    '          0: ''
    '          1: 'aa '
    '          2: 'aaaa '
    

    A expressão regular é definida como mostrado na tabela a seguir.

    Padrão Descrição
    (a+) Corresponda a letra "a" uma ou mais vezes. Este é o segundo grupo de captura.
    (\1) Corresponda a subcadeia de caracteres capturada pelo primeiro grupo de captura. Este é o terceiro grupo de captura.
    ? Corresponda zero ou um caractere de espaço.
    ((a+)(\1) ?)+ Corresponda o padrão de um ou mais caracteres "a" seguidos por uma cadeia de caracteres que corresponda o primeiro grupo de capturas seguido por zero ou um caractere de espaço uma ou mais vezes. Este é o primeiro grupo de captura.
  • Resolução de ambiguidades entre escapes octais e referências inversas. A tabela a seguir resume as diferenças na interpretação octal versus de referência inversa por expressões regulares canônicas e ECMAScript.

    Expressão regular Comportamento canônico Comportamento de ECMAScript
    \0 seguido por 0 - 2 dígitos octais Interprete como um octal. Por exemplo, \044 é sempre interpretado como um valor octal e significa "$". Mesmo comportamento.
    \ seguido por um dígito de 1 a 9, seguido por nenhum dígito decimal adicional, Interprete como referência inversa. Por exemplo, \9 sempre significa referência inversa 9, mesmo que um nono grupo de capturas não exista. Se o grupo de captura não existir, o analisador de expressão regular lança uma ArgumentException. Se existir um grupo de capturas de um único dígito decimal, faça referência inversa a esse dígito. Caso contrário, interprete o valor como literal.
    \ seguido por um dígito de 1 a 9, seguido por dígitos decimais adicionais Interprete os dígitos como um valor decimal. Se o grupo de capturas existir, interprete a expressão como referência inversa.

    Caso contrário, interprete os dígitos octais iniciais até o octal 377; ou seja, considere apenas 8 bits inferiores do valor. Interprete os dígitos restantes como literais. Por exemplo, na expressão \3000, se o grupo de capturas 300 existir, interprete como referência inversa 300; se o grupo de capturas 300 não existir, interprete como um octal 300 seguido por 0.
    Interprete como uma referência inversa convertendo todos os dígitos possíveis para um valor decimal que pode fazer referência a uma captura. Se nenhum dígito puder ser convertido, interprete como um octal usando os dígitos octais iniciais até o octal 377; interprete os dígitos restantes como literais.

Comparar usando a cultura invariável

Por padrão, quando o mecanismo de expressão regular realiza comparações sem diferenciar maiúsculas de minúsculas, ele usa as convenções de maiúsculas de minúsculas da cultura atual para determinar caracteres equivalentes em maiúsculas e minúsculas.

Porém, esse comportamento é indesejável para alguns tipos de comparações, especialmente ao comparar a entrada do usuário com os nomes de recursos do sistema, como senhas, arquivos ou URLs. O exemplo a seguir ilustra esse cenário. O código tem como objetivo bloquear o acesso a qualquer recurso cuja URL seja prefixada com FILE://. A expressão regular tenta uma correspondência sem diferenciar maiúsculas e minúsculas com a cadeia de caracteres usando a expressão regular $FILE://. No entanto, quando a cultura do sistema atual é tr-TR (Turco – Turquia ), "I" não é o equivalente maiúsculo de "i". Como resultado, a chamada para o método Regex.IsMatch retorna false e o acesso ao arquivo é permitido.

CultureInfo defaultCulture = Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = new CultureInfo("tr-TR");

string input = "file://c:/Documents.MyReport.doc";
string pattern = "FILE://";

Console.WriteLine("Culture-sensitive matching ({0} culture)...",
                  Thread.CurrentThread.CurrentCulture.Name);
if (Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase))
    Console.WriteLine("URLs that access files are not allowed.");
else
    Console.WriteLine("Access to {0} is allowed.", input);

Thread.CurrentThread.CurrentCulture = defaultCulture;
// The example displays the following output:
//       Culture-sensitive matching (tr-TR culture)...
//       Access to file://c:/Documents.MyReport.doc is allowed.
Dim defaultCulture As CultureInfo = Thread.CurrentThread.CurrentCulture
Thread.CurrentThread.CurrentCulture = New CultureInfo("tr-TR")

Dim input As String = "file://c:/Documents.MyReport.doc"
Dim pattern As String = "$FILE://"

Console.WriteLine("Culture-sensitive matching ({0} culture)...",
                  Thread.CurrentThread.CurrentCulture.Name)
If Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase) Then
    Console.WriteLine("URLs that access files are not allowed.")
Else
    Console.WriteLine("Access to {0} is allowed.", input)
End If

Thread.CurrentThread.CurrentCulture = defaultCulture
' The example displays the following output:
'       Culture-sensitive matching (tr-TR culture)...
'       Access to file://c:/Documents.MyReport.doc is allowed.

Observação

Para obter mais informações sobre comparações de cadeias de caracteres que diferenciam maiúsculas de minúsculas e usam cultura invariável, consulte Práticas recomendadas para o uso de cadeias de caracteres.

Em vez de usar comparações que não diferenciam maiúsculas de minúsculas da cultura atual, é possível especificar a opção RegexOptions.CultureInvariant para ignorar diferenças culturais no idioma e usar as convenções da cultura invariável.

Observação

A comparação usando cultura invariável está disponível apenas fornecendo o valor RegexOptions.CultureInvariant para o parâmetro options de um construtor de classe Regex ou método de correspondência padrão estático. Não está disponível como uma opção embutida.

O exemplo a seguir é idêntico ao anterior, exceto que o método estático Regex.IsMatch(String, String, RegexOptions) é chamado com opções que incluem RegexOptions.CultureInvariant. Mesmo quando a cultura atual está definida como turco (Turquia), o mecanismo de expressão regular é capaz de corresponder com sucesso "FILE" e "file" e bloquear o acesso ao recurso do arquivo.

CultureInfo defaultCulture = Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = new CultureInfo("tr-TR");

string input = "file://c:/Documents.MyReport.doc";
string pattern = "FILE://";

Console.WriteLine("Culture-insensitive matching...");
if (Regex.IsMatch(input, pattern,
                  RegexOptions.IgnoreCase | RegexOptions.CultureInvariant))
    Console.WriteLine("URLs that access files are not allowed.");
else
    Console.WriteLine("Access to {0} is allowed.", input);

Thread.CurrentThread.CurrentCulture = defaultCulture;
// The example displays the following output:
//       Culture-insensitive matching...
//       URLs that access files are not allowed.
Dim defaultCulture As CultureInfo = Thread.CurrentThread.CurrentCulture
Thread.CurrentThread.CurrentCulture = New CultureInfo("tr-TR")

Dim input As String = "file://c:/Documents.MyReport.doc"
Dim pattern As String = "$FILE://"

Console.WriteLine("Culture-insensitive matching...")
If Regex.IsMatch(input, pattern,
               RegexOptions.IgnoreCase Or RegexOptions.CultureInvariant) Then
    Console.WriteLine("URLs that access files are not allowed.")
Else
    Console.WriteLine("Access to {0} is allowed.", input)
End If
Thread.CurrentThread.CurrentCulture = defaultCulture
' The example displays the following output:
'        Culture-insensitive matching...
'        URLs that access files are not allowed.

Modo sem rastreamento inverso

Por padrão, o mecanismo regex do .NET usa o rastreamento inverso para tentar encontrar correspondências de padrão. Um mecanismo de rastreamento inverso é aquele que tenta fazer a correspondência com um padrão e, se isso falha, volta e tenta fazer a correspondência com um padrão alternativo, e assim por diante. O mecanismo de rastreamento inverso é muito rápido para casos típicos, mas desacelera à medida que o número de alternâncias de padrão aumenta, o que pode levar a rastreamentos inversos catastróficos. A opção RegexOptions.NonBacktracking, introduzida no .NET 7, não utiliza o rastreamento inverso e evita o pior cenário possível. A meta dela é proporcionar um comportamento consistentemente bom, qualquer que seja a entrada pesquisada.

A opção RegexOptions.NonBacktracking não dá suporte a tudo o que os outros mecanismos internos dão. Em particular, ela não pode ser usada em conjunto com RegexOptions.RightToLeft ou RegexOptions.ECMAScript. Também não permite os seguintes constructos no padrão:

  • Grupos atômicos
  • Referências inversas
  • Grupos de balanceamento
  • Condicionais
  • Soluções alternativas
  • Âncoras de início (\G)

RegexOptions.NonBacktracking também tem uma diferença sutil em relação à execução. Se um grupo de captura estiver em um loop, a maioria dos mecanismos regex (não .NET) fornecerá apenas o último valor correspondente para essa captura. No entanto, o mecanismo regex do .NET rastreia todos os valores capturados dentro de um loop e fornece acesso a eles. A opção RegexOptions.NonBacktracking é como a maioria das outras implementações regex e só dá suporte ao fornecimento da captura final.

Para obter mais informações sobre o rastreamento inverso, confira Rastreamento inverso em expressões regulares.

Veja também