Udostępnij za pośrednictwem


Konstrukcje alternacyjne w wyrażeniach regularnych

Konstrukcje naprzemienne modyfikują wyrażenie regularne, aby umożliwić alternatywne lub warunkowe dopasowanie. Platforma .NET obsługuje trzy konstrukcje zmiany:

Dopasowywanie wzorca za pomocą |

Możesz użyć znaku paska pionowego (|), aby dopasować dowolny z serii wzorców, gdzie | znak oddziela każdy wzorzec.

Podobnie jak znak z klasy znaków dodatnich, znak | może być używany do dopasowania dowolnego znaku z określonego zbioru pojedynczych znaków. W poniższym przykładzie użyto zarówno klasy znaku dodatniego, jak i/lub wzorca pasującego do | znaku w celu zlokalizowania wystąpień wyrazów "szary" lub "szary" w ciągu. W tym przypadku | znak tworzy wyrażenie regularne, które jest bardziej rozbudowane.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      // Regular expression using character class.
      string pattern1 = @"\bgr[ae]y\b";
      // Regular expression using either/or.
      string pattern2 = @"\bgr(a|e)y\b";

      string input = "The gray wolf blended in among the grey rocks.";
      foreach (Match match in Regex.Matches(input, pattern1))
         Console.WriteLine($"'{match.Value}' found at position {match.Index}");
      Console.WriteLine();
      foreach (Match match in Regex.Matches(input, pattern2))
         Console.WriteLine($"'{match.Value}' found at position {match.Index}");
   }
}
// The example displays the following output:
//       'gray' found at position 4
//       'grey' found at position 35
//
//       'gray' found at position 4
//       'grey' found at position 35
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        ' Regular expression using character class.
        Dim pattern1 As String = "\bgr[ae]y\b"
        ' Regular expression using either/or.
        Dim pattern2 As String = "\bgr(a|e)y\b"

        Dim input As String = "The gray wolf blended in among the grey rocks."
        For Each match As Match In Regex.Matches(input, pattern1)
            Console.WriteLine("'{0}' found at position {1}", _
                              match.Value, match.Index)
        Next
        Console.WriteLine()
        For Each match As Match In Regex.Matches(input, pattern2)
            Console.WriteLine("'{0}' found at position {1}", _
                              match.Value, match.Index)
        Next
    End Sub
End Module
' The example displays the following output:
'       'gray' found at position 4
'       'grey' found at position 35
'       
'       'gray' found at position 4
'       'grey' found at position 35           

Wyrażenie regularne używające | znaku \bgr(a|e)y\b jest interpretowane, jak pokazano w poniższej tabeli.

Wzorzec opis
\b Rozpocznij od granicy słowa.
gr Dopasuj znaki "gr".
(a|e) Dopasuj „a” lub „e”.
y\b Dopasuj wartość "y" na granicy wyrazu.

Znak | może być również używany do wykonywania dopasowania alternatywnego przy użyciu wielu znaków lub podwyrażeń, które mogą zawierać dowolną kombinację literałów i elementów języka wyrażeń regularnych. (Klasa znaków nie udostępnia tej funkcji.) W poniższym przykładzie za pomocą znaku | wyodrębnia się albo numer ubezpieczenia społecznego w USA (SSN), który jest 9-cyfrową liczbą z formatem ddd-dd-dddd, albo numer identyfikacyjny pracodawcy USA (EIN), który jest 9-cyfrową liczbą w formacie dd-ddddddd.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"\b(\d{2}-\d{7}|\d{3}-\d{2}-\d{4})\b";
      string input = "01-9999999 020-333333 777-88-9999";
      Console.WriteLine($"Matches for {pattern}:");
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine($"   {match.Value} at position {match.Index}");
   }
}
// The example displays the following output:
//       Matches for \b(\d{2}-\d{7}|\d{3}-\d{2}-\d{4})\b:
//          01-9999999 at position 0
//          777-88-9999 at position 22
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "\b(\d{2}-\d{7}|\d{3}-\d{2}-\d{4})\b"
        Dim input As String = "01-9999999 020-333333 777-88-9999"
        Console.WriteLine("Matches for {0}:", pattern)
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("   {0} at position {1}", match.Value, match.Index)
        Next
    End Sub
End Module
' The example displays the following output:
'       Matches for \b(\d{2}-\d{7}|\d{3}-\d{2}-\d{4})\b:
'          01-9999999 at position 0
'          777-88-9999 at position 22

Wyrażenie \b(\d{2}-\d{7}|\d{3}-\d{2}-\d{4})\b regularne jest interpretowane, jak pokazano w poniższej tabeli:

Wzorzec opis
\b Zacznij na granicy wyrazu.
(\d{2}-\d{7}|\d{3}-\d{2}-\d{4}) Dopasuj jedną z następujących wartości: dwie cyfry dziesiętne, po których następuje łącznik, po którym następuje siedem cyfr dziesiętnych; lub trzy cyfry dziesiętne, łącznik, dwie cyfry dziesiętne, inny łącznik i cztery cyfry dziesiętne.
\b Zakończ mecz na granicy wyrazu.

Dopasowywanie warunkowe za pomocą wyrażenia

Ten element języka próbuje dopasować jeden z dwóch wzorców w zależności od tego, czy może być zgodny ze wzorcem początkowym. Jego składnia to:

(?( wyrażenie)tak)

lub

(?( wyrażenie)tak|Nie)

gdzie wyrażenie jest początkowym wzorcem do dopasowania, tak jest wzorcem do dopasowania, jeśli wyrażenie jest dopasowane, a nie jest opcjonalnym wzorcem do dopasowania, jeśli wyrażenie nie jest dopasowane (jeśli wzorzec nie nie jest podany, jest to odpowiednik pustego nie). Aparat wyrażeń regularnych traktuje wyrażenie jako asercję o zerowej szerokości. Oznacza to, że aparat wyrażeń regularnych nie przechodzi do strumienia wejściowego po obliczeniu wyrażenia. W związku z tym ta konstrukcja jest równoważna następującym:

(?(?= wyrażenie)tak|Nie)

gdzie (?=wyrażenie) jest konstrukcją asercji o zerowej szerokości. (Aby uzyskać więcej informacji, zobacz Konstrukcje grupowania.) Ponieważ aparat wyrażeń regularnych interpretuje wyrażenie jako kotwicę (asercja o zerowej szerokości), wyrażenie musi być albo asercją o zerowej szerokości (aby uzyskać więcej informacji, zobacz Kotwice) albo podwyrażeniem, które jest również zawarte w yes. W przeciwnym razie nie można dopasować wzorca 'yes'.

Uwaga

Jeśli wyrażenie jest nazwaną lub numerowaną grupą przechwytywania, konstrukcja alternatywy jest interpretowana jako test przechwytywania. Aby uzyskać więcej informacji, zobacz następną sekcję Dopasowywanie warunkowe na podstawie prawidłowej grupy przechwytywania. Innymi słowy, silnik wyrażeń regularnych nie próbuje dopasować przechwyconego podciągu, ale zamiast tego sprawdza, czy grupa jest obecna czy nieobecna.

Poniższy przykład to odmiana przykładu przedstawionego w sekcji Dopasowywanie wzorca Either/Or z |. Używa dopasowania warunkowego, aby określić, czy pierwsze trzy znaki po granicy wyrazu to dwie cyfry, po których następuje łącznik. Jeśli tak, próbuje dopasować amerykański numer identyfikacyjny pracodawcy (EIN). Jeśli nie, próbuje dopasować amerykański numer ubezpieczenia społecznego (SSN).

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"\b(?(\d{2}-)\d{2}-\d{7}|\d{3}-\d{2}-\d{4})\b";
      string input = "01-9999999 020-333333 777-88-9999";
      Console.WriteLine($"Matches for {pattern}:");
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine($"   {match.Value} at position {match.Index}");
   }
}
// The example displays the following output:
//       Matches for \b(\d{2}-\d{7}|\d{3}-\d{2}-\d{4})\b:
//          01-9999999 at position 0
//          777-88-9999 at position 22
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "\b(?(\d{2}-)\d{2}-\d{7}|\d{3}-\d{2}-\d{4})\b"
        Dim input As String = "01-9999999 020-333333 777-88-9999"
        Console.WriteLine("Matches for {0}:", pattern)
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("   {0} at position {1}", match.Value, match.Index)
        Next
    End Sub
End Module
' The example displays the following output:
'       Matches for \b(?(\d{2}-)\d{2}-\d{7}|\d{3}-\d{2}-\d{4})\b:
'          01-9999999 at position 0
'          777-88-9999 at position 22

Wzorzec \b(?(\d{2}-)\d{2}-\d{7}|\d{3}-\d{2}-\d{4})\b wyrażenia regularnego jest interpretowany, jak przedstawiono w poniższej tabeli.

Wzorzec opis
\b Zacznij na granicy wyrazu.
(?(\d{2}-) Ustal, czy następne trzy znaki składają się z dwóch cyfr, po których następuje łącznik.
\d{2}-\d{7} Jeśli poprzedni wzorzec pasuje, dopasuj dwie cyfry, po których następuje łącznik, po którym następuje siedem cyfr.
\d{3}-\d{2}-\d{4} Jeśli poprzedni wzorzec nie jest zgodny, dopasuj trzy cyfry dziesiętne, łącznik, dwie cyfry dziesiętne, inny łącznik i cztery cyfry dziesiętne.
\b Dopasuj granicę wyrazu.

Dopasowywanie warunkowe na podstawie prawidłowej przechwyconej grupy

Ten element języka próbuje dopasować jeden z dwóch wzorców w zależności od tego, czy pasował do określonej grupy przechwytywania. Jego składnia to:

(?( nazwa)tak)

lub

(?( nazwa)tak|Nie)

lub

(?( numer)tak)

lub

(?( numer)tak|Nie)

gdzie nazwa jest nazwą, a liczba jest liczbą grupy przechwytywania, tak jest wyrażeniem do dopasowania, jeśli nazwa lub liczba ma dopasowanie, a nie jest opcjonalnym wyrażeniem do dopasowania, jeśli tak nie jest (jeśli wzorzec nie nie jest podany, jest to równoważne pustemu nie).

Jeśli nazwa nie odpowiada nazwie grupy przechwytywania używanej we wzorcu wyrażenia regularnego, konstrukcja zmiany jest interpretowana jako test wyrażeń, jak wyjaśniono w poprzedniej sekcji. Zazwyczaj oznacza to, że wyrażenie daje wartość false. Jeśli liczba nie odpowiada numerowanej grupie przechwytywania, która jest używana we wzorcu wyrażenia regularnego, aparat wyrażeń regularnych zgłasza wartość ArgumentException.

Poniższy przykład to odmiana przykładu, który pojawia się w sekcji Dopasowywanie na zasadzie „albo/albo” z użyciem znaku |. Używa grupy przechwytywania o nazwie n2 , która składa się z dwóch cyfr, po których następuje łącznik. Konstrukcja alternacji sprawdza, czy ta grupa przechwytywana została odnaleziona w ciągu wejściowym. Jeśli tak, konstrukcja alternacji próbuje dopasować ostatnie siedem cyfr dziewięciocyfrowego amerykańskiego numeru identyfikacyjnego pracodawcy (EIN). Jeśli tak nie jest, próbuje dopasować dziewięciocyfrowy amerykański numer ubezpieczenia społecznego (SSN).

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"\b(?<n2>\d{2}-)?(?(n2)\d{7}|\d{3}-\d{2}-\d{4})\b";
      string input = "01-9999999 020-333333 777-88-9999";
      Console.WriteLine($"Matches for {pattern}:");
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine($"   {match.Value} at position {match.Index}");
   }
}
// The example displays the following output:
//       Matches for \b(?<n2>\d{2}-)?(?(n2)\d{7}|\d{3}-\d{2}-\d{4})\b:
//          01-9999999 at position 0
//          777-88-9999 at position 22
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "\b(?<n2>\d{2}-)?(?(n2)\d{7}|\d{3}-\d{2}-\d{4})\b"
        Dim input As String = "01-9999999 020-333333 777-88-9999"
        Console.WriteLine("Matches for {0}:", pattern)
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("   {0} at position {1}", match.Value, match.Index)
        Next
    End Sub
End Module

Wzorzec wyrażenia regularnego \b(?<n2>\d{2}-)?(?(n2)\d{7}|\d{3}-\d{2}-\d{4})\b jest interpretowany tak, jak pokazano w poniższej tabeli.

Wzorzec opis
\b Zacznij na granicy wyrazu.
(?<n2>\d{2}-)? Dopasuj zero lub jedno wystąpienie dwóch cyfr, po którym następuje łącznik. Nadaj nazwę tej grupie przechwytywania n2.
(?(n2) Sprawdź, czy n2 został dopasowany w ciągu wejściowym.
\d{7} Jeśli n2 została dopasowana, dopasuj siedem cyfr dziesiętnych.
|\d{3}-\d{2}-\d{4} Jeśli n2 nie zostało dopasowane, dopasuj trzy cyfry dziesiętne, łącznik, dwie cyfry dziesiętne, inny łącznik i cztery cyfry dziesiętne.
\b Dopasuj granicę wyrazu.

Odmiana tego przykładu, która używa grupy numerowanej zamiast nazwanej grupy, jest pokazana w poniższym przykładzie. Jego wzorzec wyrażenia regularnego to \b(\d{2}-)?(?(1)\d{7}|\d{3}-\d{2}-\d{4})\b.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"\b(\d{2}-)?(?(1)\d{7}|\d{3}-\d{2}-\d{4})\b";
      string input = "01-9999999 020-333333 777-88-9999";
      Console.WriteLine($"Matches for {pattern}:");
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine($"   {match.Value} at position {match.Index}");
   }
}
// The example display the following output:
//       Matches for \b(\d{2}-)?(?(1)\d{7}|\d{3}-\d{2}-\d{4})\b:
//          01-9999999 at position 0
//          777-88-9999 at position 22
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "\b(\d{2}-)?(?(1)\d{7}|\d{3}-\d{2}-\d{4})\b"
        Dim input As String = "01-9999999 020-333333 777-88-9999"
        Console.WriteLine("Matches for {0}:", pattern)
        For Each match As Match In Regex.Matches(input, pattern)
            Console.WriteLine("   {0} at position {1}", match.Value, match.Index)
        Next
    End Sub
End Module
' The example displays the following output:
'       Matches for \b(\d{2}-)?(?(1)\d{7}|\d{3}-\d{2}-\d{4})\b:
'          01-9999999 at position 0
'          777-88-9999 at position 22

Zobacz też