Condividi tramite


Costrutti di backreference

I backreference forniscono un modo pratico per identificare un carattere ripetuto o una sottostringa all'interno di una stringa. Ad esempio, se nella stringa di input sono contenute più occorrenze di una sottostringa arbitraria, è possibile creare una corrispondenza della prima occorrenza con un gruppo Capture, quindi utilizzare un backreference per individuare le corrispondenze con le occorrenze successive della sottostringa.

NotaNota

Una sintassi separata è utilizzata per fare riferimento a gruppi di acquisizione denominati e numerati nelle stringhe di sostituzione.Per ulteriori informazioni, vedere Sostituzioni.

.NET Framework definisce elementi di linguaggio separati per fare riferimento a gruppi di acquisizione numerati e denominati. Per ulteriori informazioni sui gruppi di acquisizione, vedere Costrutti di raggruppamento.

Backreference numerati

Un backreference numerato utilizza la sintassi seguente:

\numero

dove numero è la posizione ordinale di un gruppo di acquisizione nell'espressione regolare. Ad esempio, \4 corrisponde al contenuto del quarto gruppo di acquisizione. Se il numero non è definito nel criterio di espressione regolare, si verifica un errore di analisi e il motore delle espressioni regolari genera un ArgumentException. Ad esempio, l'espressione regolare \b(\w+)\s\1 è valida perché (\w+) è il primo e l'unico gruppo di acquisizione nell'espressione. D'altra parte, \b(\w+)\s\2 non è valido e genera un'eccezione di argomento, perché non esiste alcun gruppo di acquisizione numerato \2.

Si noti l'ambiguità tra i codici di escape ottali (ad esempio, \16) e backreference \number che utilizzano la stessa notazione. L'ambiguità viene risolta nel modo seguente:

  • Le espressioni da \1 a \9 sono sempre interpretate come backreference, non come codici ottali.

  • Se la prima cifra di un'espressione composta da più cifre è 8 o 9 (ad esempio \80 o \91), l'espressione verrà interpretata come un valore letterale.

  • Le espressioni da \10 e superiori vengono considerate backreference se sono presenti backreference corrispondenti a quel numero; in caso contrario, vengono interpretate come codici ottali.

  • L'inclusione di un riferimento a un numero di gruppo non definito in un'espressione regolare provoca un errore di analisi e il motore delle espressioni regolari genera un ArgumentException.

Se l'ambiguità costituisce un problema, è possibile utilizzare la notazione \k<nome> che non è ambigua e non può essere confusa con i la notazione peri numeri ottali. Allo stesso modo, i codici esadecimali quali \xdd non sono ambigui e non possono quindi venire confusi con backreference.

Nel seguente esempio vengono individuati caratteri alfanumerici doppi in una stringa. Definisce un'espressione regolare, (\w)\1, costituita dagli elementi seguenti.

Elemento

Oggetto di descrizione

(\w)

Corrisponde a un carattere alfanumerico e lo assegna al primo gruppo di acquisizione.

\1

Corrisponde al carattere successivo uguale al valore del primo gruppo di acquisizione.

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

Backreference denominati

Un backreference denominato viene definito mediante la sintassi seguente:

\k<name>

oppure:

\k'name'

dove nome è il nome di un gruppo di acquisizione definito nel modello di espressione regolare. Se il nome non è definito nel criterio di espressione regolare, si verifica un errore di analisi e il motore delle espressioni regolari genera un ArgumentException.

Nel seguente esempio vengono individuati caratteri alfanumerici doppi in una stringa. Definisce un'espressione regolare, (?<char>\w)\k<char>, costituita dagli elementi seguenti.

Elemento

Oggetto di descrizione

(?<char>\w)

Corrisponde a un carattere alfanumerico e lo assegna a un gruppo di acquisizione denominato char.

\k<char>

Corrisponde al carattere successivo uguale al valore del gruppo di acquisizione char.

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

Il nome può anche essere la rappresentazione in forma di stringa di un numero. Nell'esempio seguente viene utilizzata l'espressione regolare (?<2>\w)\k<2> per trovare caratteri alfanumerici doppi in una stringa.

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

Corrispondenza dei backreference

Un riferimento a una corrispondenza memorizzata si riferisce alla definizione più recente di un gruppo (quella che si trova subito a sinistra, quando l'analisi procede da sinistra a destra). Quando un gruppo genera più acquisizioni, un backreference farà riferimento all'acquisizione più recente.

Nell'esempio seguente viene incluso un modello di espressione regolare, (?<1>a)(?<1>\1b)*, che ridefinisce il gruppo denominato \1. Nella tabella riportata di seguito vengono descritti i singoli modelli nell'espressione regolare.

Modello

Oggetto di descrizione

(?<1>a)

Corrisponde al carattere "a" e assegna il risultato al gruppo di acquisizione denominato 1.

(?<1>\1b)*

Trova la corrispondenza per 0 o 1 occorrenza del gruppo denominato 1 insieme a una "b" e assegna il risultato al gruppo di acquisizione denominato 1.

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
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

Nel confronto dell'espressione regolare con la stringa di input ("aababb"), il motore delle espressioni regolari esegue le seguenti operazioni:

  1. parte dall'inizio della stringa e trova una corrispondenza riuscita per "a" con l'espressione (?<1>a). A questo punto il valore del gruppo 1 è "a".

  2. Avanza al secondo carattere e trova una corrispondenza corretta della stringa "ab" con l'espressione \1b o "ab". Assegna quindi il risultato, "ab", a \1.

  3. Avanza al quarto carattere. Per l'espressione (?<1>\1b) una corrispondenza deve essere individuata zero o più volte, ai fini di una corrispondenza corretta alla stringa "abb" con l'espressione \1b. Assegna il risultato, "abb", nuovamente a \1.

In questo esempio, * è un quantificatore di cicli --viene eseguito ripetutamente finché il motore delle espressioni regolari non trova una corrispondenza con il modello che definisce. I quantificatori di cicli non cancellano le definizioni di gruppi.

Se un gruppo non ha acquisito alcuna sottostringa, un backreference a tale gruppo risulterà non definito e non verrà mai soddisfatto. Ciò è illustrato dal modello di espressione regolare \b(\p{Lu}{2})(\d{2})?(\p{Lu}{2})\b, definito nel modo seguente:

Modello

Oggetto di descrizione

\b

Inizia la corrispondenza sul confine di parola.

(\p{Lu}{2})

Corrisponde a due lettere maiuscole. Equivale al primo gruppo di acquisizione.

(\d{2})?

Corrisponde a zero o a un'occorrenza di due cifre decimali. Equivale al secondo gruppo di acquisizione.

(\p{Lu}{2})

Corrisponde a due lettere maiuscole. Equivale al terzo gruppo di acquisizione.

\b

Termina la corrispondenza sul confine di parola.

Una stringa di input può corrispondere a questa espressione regolare anche se le due cifre decimali definite dal secondo gruppo di acquisizione non sono presenti. L'esempio seguente mostra che anche se la corrispondenza viene eseguita correttamente, viene individuato un gruppo di acquisizione vuoto tra due gruppi di acquisizione con corrispondenza corretta.

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
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

Vedere anche

Concetti

Elementi del linguaggio di espressioni regolari