Construtores de referência inversa em expressões regularesBackreference Constructs in Regular Expressions

As referências inversas fornecem uma maneira conveniente de identificar um caractere ou subcadeia de caracteres repetida em uma cadeia de caracteres.Backreferences provide a convenient way to identify a repeated character or substring within a string. Por exemplo, se a cadeia de caracteres de entrada contiver várias ocorrências de uma subcadeia de caracteres arbitrária, você poderá corresponder a primeira ocorrência a um grupo de captura e, em seguida, usar uma referência inversa para corresponder às ocorrências subsequentes da subcadeia de caracteres.For example, if the input string contains multiple occurrences of an arbitrary substring, you can match the first occurrence with a capturing group, and then use a backreference to match subsequent occurrences of the substring.

Observação

Uma sintaxe separada é usada para se referir a grupos de captura nomeados e numerados em cadeias de caracteres de substituição.A separate syntax is used to refer to named and numbered capturing groups in replacement strings. Para saber mais, confira Substituições.For more information, see Substitutions.

O .NET define elementos de linguagem separados para se referir a grupos de captura nomeados e numerados..NET defines separate language elements to refer to numbered and named capturing groups. Para saber mais sobre captura de grupos, confira Constructos de agrupamento.For more information about capturing groups, see Grouping Constructs.

Referências inversas numeradasNumbered Backreferences

Uma referência inversa numerada usa a seguinte sintaxe:A numbered backreference uses the following syntax:

\ número\ number

em que number é a posição ordinal do grupo de captura na expressão regular.where number is the ordinal position of the capturing group in the regular expression. Por exemplo, \4 corresponde ao conteúdo do quarto grupo de captura.For example, \4 matches the contents of the fourth capturing group. Se number não for definido no padrão da expressão regular, ocorrerá um erro de análise e o mecanismo de expressões regulares gerará um ArgumentException.If number is not defined in the regular expression pattern, a parsing error occurs, and the regular expression engine throws an ArgumentException. Por exemplo, a expressão regular \b(\w+)\s\1 é válida porque (\w+) é o primeiro e único grupo de captura na expressão.For example, the regular expression \b(\w+)\s\1 is valid, because (\w+) is the first and only capturing group in the expression. Por outro lado, \b(\w+)\s\2 é inválida e gera uma exceção de argumento porque não há nenhum grupo de captura com o número \2.On the other hand, \b(\w+)\s\2 is invalid and throws an argument exception, because there is no capturing group numbered \2. Além disso, quando number identifica um grupo de captura em uma determinada posição ordinal, mas um nome numérico diferente da posição ordinal desse grupo de captura é atribuído a ele, o analisador de expressões regulares também gera um ArgumentException.In addition, if number identifies a capturing group in a particular ordinal position, but that capturing group has been assigned a numeric name different than its ordinal position, the regular expression parser also throws an ArgumentException.

Observe a ambiguidade entre códigos de escape octais (como \16) e as referências inversas \number que usam a mesma notação.Note the ambiguity between octal escape codes (such as \16) and \number backreferences that use the same notation. Essa ambiguidade é resolvida da seguinte maneira:This ambiguity is resolved as follows:

  • As expressões \1 a \9 sempre são interpretadas como referências inversas e não como códigos octais.The expressions \1 through \9 are always interpreted as backreferences, and not as octal codes.

  • Se o primeiro dígito de uma expressão de diversos for 8 ou 9 (como \80 ou \91), a expressão será interpretada como uma literal.If the first digit of a multidigit expression is 8 or 9 (such as \80 or \91), the expression as interpreted as a literal.

  • Expressões de \10 e maiores serão consideradas referências inversas se houver uma referência inversa correspondente àquele número, caso contrário, elas serão interpretadas como códigos octais.Expressions from \10 and greater are considered backreferences if there is a backreference corresponding to that number; otherwise, they are interpreted as octal codes.

  • Se uma expressão regular contiver uma referência inversa para um número de grupo indefinido, ocorrerá um erro de análise e o mecanismo de expressões regulares gerará um ArgumentException.If a regular expression contains a backreference to an undefined group number, a parsing error occurs, and the regular expression engine throws an ArgumentException.

Se a ambiguidade for um problema, você poderá usar a \k< name > notação de nome, que não é ambígua e não pode ser confundida com códigos de caracteres octais.If the ambiguity is a problem, you can use the \k<name> notation, which is unambiguous and cannot be confused with octal character codes. Da mesma forma, os códigos hexadecimais como \xdd são não ambíguos e não podem ser confundidos com referências inversas.Similarly, hexadecimal codes such as \xdd are unambiguous and cannot be confused with backreferences.

O exemplo a seguir localiza caracteres de palavra duplicados em uma cadeia de caracteres.The following example finds doubled word characters in a string. Ele define uma expressão regular, (\w)\1, que consiste nos elementos a seguir.It defines a regular expression, (\w)\1, which consists of the following elements.

ElementoElement DescriptionDescription
(\w) Corresponde a um caractere de palavra e o atribui ao primeiro grupo de captura.Match a word character and assign it to the first capturing group.
\1 Corresponde ao próximo caractere que é o mesmo que o valor do primeiro grupo de captura.Match the next character that is the same as the value of the first capturing group.
using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"(\w)\1";
      string input = "trellis llama webbing dresser swagger";
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine("Found '{0}' at position {1}.",
                           match.Value, match.Index);
   }
}
// The example displays the following output:
//       Found 'll' at position 3.
//       Found 'll' at position 8.
//       Found 'bb' at position 16.
//       Found 'ss' at position 25.
//       Found 'gg' at position 33.
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "(\w)\1"
        Dim input As String = "trellis llama webbing dresser swagger"
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("Found '{0}' at position {1}.", _
                              match.Value, match.Index)
        Next
    End Sub
End Module
' The example displays the following output:
'       Found 'll' at position 3.
'       Found 'll' at position 8.
'       Found 'bb' at position 16.
'       Found 'ss' at position 25.
'       Found 'gg' at position 33.

Referências inversas nomeadasNamed Backreferences

Uma referência inversa nomeada é definida usando a sintaxe a seguir:A named backreference is defined by using the following syntax:

\k<nome do>\k< name >

ou:or:

\k'nome do'\k' name '

em que name é o nome de um grupo de captura definido no padrão da expressão regular.where name is the name of a capturing group defined in the regular expression pattern. Se name não for definido no padrão da expressão regular, ocorrerá um erro de análise e o mecanismo de expressões regulares gerará um ArgumentException.If name is not defined in the regular expression pattern, a parsing error occurs, and the regular expression engine throws an ArgumentException.

O exemplo a seguir localiza caracteres de palavra duplicados em uma cadeia de caracteres.The following example finds doubled word characters in a string. Ele define uma expressão regular, (?<char>\w)\k<char>, que consiste nos elementos a seguir.It defines a regular expression, (?<char>\w)\k<char>, which consists of the following elements.

ElementoElement DescriptionDescription
(?<char>\w) Corresponde a um caractere de palavra e o atribui a um grupo de captura chamado char.Match a word character and assign it to a capturing group named char.
\k<char> Corresponde ao próximo caractere que é o mesmo que o valor do grupo de captura char.Match the next character that is the same as the value of the char capturing group.
using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"(?<char>\w)\k<char>";
      string input = "trellis llama webbing dresser swagger";
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine("Found '{0}' at position {1}.",
                           match.Value, match.Index);
   }
}
// The example displays the following output:
//       Found 'll' at position 3.
//       Found 'll' at position 8.
//       Found 'bb' at position 16.
//       Found 'ss' at position 25.
//       Found 'gg' at position 33.
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "(?<char>\w)\k<char>"
        Dim input As String = "trellis llama webbing dresser swagger"
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("Found '{0}' at position {1}.", _
                              match.Value, match.Index)
        Next
    End Sub
End Module
' The example displays the following output:
'       Found 'll' at position 3.
'       Found 'll' at position 8.
'       Found 'bb' at position 16.
'       Found 'ss' at position 25.
'       Found 'gg' at position 33.

Referências inversas numéricas nomeadasNamed numeric backreferences

Em uma referência inversa nomeada com \k, name também pode ser a representação da cadeia de caracteres de um número.In a named backreference with \k, name can also be the string representation of a number. Por exemplo, o exemplo a seguir usa a expressão regular (?<2>\w)\k<2> para localizar caracteres de palavra duplicados em uma cadeia de caracteres.For example, the following example uses the regular expression (?<2>\w)\k<2> to find doubled word characters in a string. Nesse caso, o exemplo define um grupo de captura explicitamente nomeado como "2", e a referência inversa é correspondentemente denominada "2".In this case, the example defines a capturing group that is explicitly named "2", and the backreference is correspondingly named "2".

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"(?<2>\w)\k<2>";
      string input = "trellis llama webbing dresser swagger";
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine("Found '{0}' at position {1}.",
                           match.Value, match.Index);
   }
}
// The example displays the following output:
//       Found 'll' at position 3.
//       Found 'll' at position 8.
//       Found 'bb' at position 16.
//       Found 'ss' at position 25.
//       Found 'gg' at position 33.
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "(?<2>\w)\k<2>"
        Dim input As String = "trellis llama webbing dresser swagger"
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("Found '{0}' at position {1}.", _
                              match.Value, match.Index)
        Next
    End Sub
End Module
' The example displays the following output:
'       Found 'll' at position 3.
'       Found 'll' at position 8.
'       Found 'bb' at position 16.
'       Found 'ss' at position 25.
'       Found 'gg' at position 33.

Se name é a representação de cadeia de caracteres de um número e nenhum grupo de captura tem esse nome, \k<name> é o mesmo que o \number da referência inversa, em que number é a posição ordinal da captura.If name is the string representation of a number, and no capturing group has that name, \k<name> is the same as the backreference \number, where number is the ordinal position of the capture. No exemplo a seguir, há um único grupo de captura nomeado char.In the following example, there is a single capturing group named char. O constructo de referência inversa se refere a ele como \k<1>.The backreference construct refers to it as \k<1>. Conforme demonstrado pela saída do exemplo, a chamada para o Regex.IsMatch é bem-sucedida porque char é o primeiro grupo de captura.As the output from the example shows, the call to the Regex.IsMatch succeeds because char is the first capturing group.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      Console.WriteLine(Regex.IsMatch("aa", @"(?<char>\w)\k<1>"));
      // Displays "True".
   }
}

Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Console.WriteLine(Regex.IsMatch("aa", "(?<char>\w)\k<1>"))
        ' Displays "True".
    End Sub
End Module

No entanto, se name é a representação de cadeia de caracteres de um número e um nome numérico foi explicitamente atribuído a um grupo de captura nessa posição, o analisador de expressão regular não pode identificar o grupo de captura por sua posição ordinal.However, if name is the string representation of a number and the capturing group in that position has been explicitly assigned a numeric name, the regular expression parser cannot identify the capturing group by its ordinal position. Em vez disso, ele gera um ArgumentException .Instead, it throws an ArgumentException. O único grupo de captura no exemplo a seguir é denominado "2".The only capturing group in the following example is named "2". Já que o constructo \k é usado para definir uma referência inversa denominada "1", o analisador de expressão regular não pode identificar o primeiro grupo de captura e gera uma exceção.Because the \k construct is used to define a backreference named "1", the regular expression parser is unable to identify the first capturing group and throws an exception.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      Console.WriteLine(Regex.IsMatch("aa", @"(?<2>\w)\k<1>"));
      // Throws an ArgumentException.
   }
}

Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Console.WriteLine(Regex.IsMatch("aa", "(?<2>\w)\k<1>"))
        ' Throws an ArgumentException.
    End Sub
End Module

A que as referências inversas correspondemWhat Backreferences Match

Uma referência inversa refere-se à definição mais recente de um grupo (a definição mais imediatamente à esquerda, ao fazer a correspondência da esquerda para a direita).A backreference refers to the most recent definition of a group (the definition most immediately to the left, when matching left to right). Quando um grupo faz várias capturas, uma referência inversa refere-se à captura mais recente.When a group makes multiple captures, a backreference refers to the most recent capture.

O exemplo a seguir inclui um padrão de expressão regular, (?<1>a)(?<1>\1b)*, que redefine o grupo nomeado \1.The following example includes a regular expression pattern, (?<1>a)(?<1>\1b)*, which redefines the \1 named group. A tabela a seguir descreve cada padrão na expressão regular.The following table describes each pattern in the regular expression.

PadrãoPattern DescriçãoDescription
(?<1>a) Corresponde ao caractere "a" e atribui o resultado ao grupo de captura chamado 1.Match the character "a" and assign the result to the capturing group named 1.
(?<1>\1b)* Corresponda zero ou mais ocorrências ao grupo chamado 1 junto com "b" e atribua o resultado ao grupo de captura chamado 1.Match zero or more occurrences of the group named 1 along with a "b", and assign the result to the capturing group named 1.
using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"(?<1>a)(?<1>\1b)*";
      string input = "aababb";
      foreach (Match match in Regex.Matches(input, pattern))
      {
         Console.WriteLine("Match: " + match.Value);
         foreach (Group group in match.Groups)
            Console.WriteLine("   Group: " + group.Value);
      }
   }
}
// The example displays the following output:
//          Group: aababb
//          Group: abb
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "(?<1>a)(?<1>\1b)*"
        Dim input As String = "aababb"
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("Match: " + match.Value)
            For Each group As Group In match.Groups
                Console.WriteLIne("   Group: " + group.Value)
            Next
        Next
    End Sub
End Module
' The example display the following output:
'          Group: aababb
'          Group: abb

Comparando a expressão regular com a cadeia de caracteres de entrada ("aababb"), o mecanismo de expressões regulares realiza as seguintes operações:In comparing the regular expression with the input string ("aababb"), the regular expression engine performs the following operations:

  1. Ele começa no início da cadeia de caracteres e corresponde com êxito o “a” com a expressão (?<1>a).It starts at the beginning of the string, and successfully matches "a" with the expression (?<1>a). O valor do grupo 1 agora é "a".The value of the 1 group is now "a".

  2. Ele avança para o segundo caractere e corresponde com êxito a cadeia de caracteres "ab" com a expressão \1b, ou "ab".It advances to the second character, and successfully matches the string "ab" with the expression \1b, or "ab". Em seguida, atribui o resultado, "ab", a \1.It then assigns the result, "ab" to \1.

  3. Ele avança para o quarto caractere.It advances to the fourth character. A expressão (?<1>\1b)* deve ser correspondida zero ou mais vezes, de forma que corresponda com êxito a cadeia de caracteres “abb” à expressão \1b.The expression (?<1>\1b)* is to be matched zero or more times, so it successfully matches the string "abb" with the expression \1b. Ela atribui o resultado, “abb”, a \1.It assigns the result, "abb", back to \1.

Neste exemplo, * é um quantificador looping – ele é avaliado repetidamente até que o mecanismo de expressões regulares não corresponda ao padrão definido.In this example, * is a looping quantifier -- it is evaluated repeatedly until the regular expression engine cannot match the pattern it defines. Os quantificadores de looping não limpam definições de grupo.Looping quantifiers do not clear group definitions.

Se um grupo não capturou nenhuma subcadeia de caracteres, uma referência inversa a esse grupo é indefinida e nunca corresponde.If a group has not captured any substrings, a backreference to that group is undefined and never matches. Isso é ilustrado pelo padrão de expressão regular \b(\p{Lu}{2})(\d{2})?(\p{Lu}{2})\b que é definido da seguinte maneira:This is illustrated by the regular expression pattern \b(\p{Lu}{2})(\d{2})?(\p{Lu}{2})\b, which is defined as follows:

PadrãoPattern DescriçãoDescription
\b Começa a correspondência em um limite de palavra.Begin the match on a word boundary.
(\p{Lu}{2}) Corresponde a duas letras maiúsculas.Match two uppercase letters. Este é o primeiro grupo de captura.This is the first capturing group.
(\d{2})? Corresponde a zero ou uma ocorrência de dois dígitos decimais.Match zero or one occurrence of two decimal digits. Este é o segundo grupo de captura.This is the second capturing group.
(\p{Lu}{2}) Corresponde a duas letras maiúsculas.Match two uppercase letters. Este é o terceiro grupo de captura.This is the third capturing group.
\b Termina a correspondência em um limite de palavra.End the match on a word boundary.

Uma cadeia de caracteres de entrada pode corresponder a essa expressão regular, mesmo se os dois dígitos decimais que são definidos pelo segundo grupo de captura não estiverem presentes.An input string can match this regular expression even if the two decimal digits that are defined by the second capturing group are not present. O exemplo a seguir mostra que, embora a correspondência seja bem-sucedida, um grupo de captura vazio foi encontrado entre dois grupos de captura com êxito.The following example shows that even though the match is successful, an empty capturing group is found between two successful capturing groups.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"\b(\p{Lu}{2})(\d{2})?(\p{Lu}{2})\b";
      string[] inputs = { "AA22ZZ", "AABB" };
      foreach (string input in inputs)
      {
         Match match = Regex.Match(input, pattern);
         if (match.Success)
         {
            Console.WriteLine("Match in {0}: {1}", input, match.Value);
            if (match.Groups.Count > 1)
            {
               for (int ctr = 1; ctr <= match.Groups.Count - 1; ctr++)
               {
                  if (match.Groups[ctr].Success)
                     Console.WriteLine("Group {0}: {1}",
                                       ctr, match.Groups[ctr].Value);
                  else
                     Console.WriteLine("Group {0}: <no match>", ctr);
               }
            }
         }
         Console.WriteLine();
      }
   }
}
// The example displays the following output:
//       Match in AA22ZZ: AA22ZZ
//       Group 1: AA
//       Group 2: 22
//       Group 3: ZZ
//
//       Match in AABB: AABB
//       Group 1: AA
//       Group 2: <no match>
//       Group 3: BB
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "\b(\p{Lu}{2})(\d{2})?(\p{Lu}{2})\b"
        Dim inputs() As String = {"AA22ZZ", "AABB"}
        For Each input As String In inputs
            Dim match As Match = Regex.Match(input, pattern)
            If match.Success Then
                Console.WriteLine("Match in {0}: {1}", input, match.Value)
                If match.Groups.Count > 1 Then
                    For ctr As Integer = 1 To match.Groups.Count - 1
                        If match.Groups(ctr).Success Then
                            Console.WriteLine("Group {0}: {1}", _
                                              ctr, match.Groups(ctr).Value)
                        Else
                            Console.WriteLine("Group {0}: <no match>", ctr)
                        End If
                    Next
                End If
            End If
            Console.WriteLine()
        Next
    End Sub
End Module
' The example displays the following output:
'       Match in AA22ZZ: AA22ZZ
'       Group 1: AA
'       Group 2: 22
'       Group 3: ZZ
'       
'       Match in AABB: AABB
'       Group 1: AA
'       Group 2: <no match>
'       Group 3: BB

Veja tambémSee also