Поделиться через


Конструкции группировки в регулярных выражениях

Конструкции группирования отображают части выражений регулярных выражений и захватывают части строки входной строки. Конструкции группирования можно использовать в следующих целях.

  • Соответствует подэкспрессии, повторяющейся в входной строке.
  • Применение квантификатору к части выражения с несколькими языковыми элементами регулярных выражений. Дополнительные сведения о квантификаторах см. в разделе Quantifiers.
  • Включите в строку, возвращаемую методами и Match.Result вложенными выражениямиRegex.Replace.
  • Извлечение отдельных частей выражения из свойства Match.Groups и обработка их по отдельности от всего текста.

В следующей таблице перечислены конструкции группирования, поддерживаемые подсистемой регулярных выражений .NET, и указывает, фиксируются ли они или не являются.

Конструкция группирования Захватываемая или незахватываемая
Сопоставляемые части выражения Захватываемая
Именованные сопоставленные части выражения Захватываемая
Сбалансированные определения группы Захватываемая
Незахватываемые группы Незахватываемая
Параметры группы Незахватываемая
Утверждения положительного просмотра вперед нулевой ширины Незахватываемая
Утверждения отрицательного просмотра вперед нулевой ширины Незахватываемая
Утверждения положительного просмотра назад нулевой ширины Незахватываемая
Утверждения отрицательного просмотра назад нулевой ширины Незахватываемая
Атомарные группы Незахватываемая

Сведения о группах и объектной модели регулярных выражений см. в разделе Конструкции группирования и объекты регулярных выражений.

Сопоставляемые части выражения

Следующая конструкция группирования выделяет сопоставленную часть выражения:

( subexpression )

Здесь подэкспрессия является любым допустимым шаблоном регулярного выражения. Записи, использующие круглые скобки, автоматически нумеруются слева направо на основе порядка открывающих скобок в регулярном выражении, начиная с 1. Однако именованные группы отслеживания всегда упорядочены в последний раз после именованных групп отслеживания. Запись, нумеруемая 0, — это текст, соответствующий всему шаблону регулярного выражения.

Примечание.

По умолчанию языковой элемент (часть выражения) выделяет сопоставленную часть выражения. Но если RegexOptions параметр соответствующего метода сопоставления шаблонов регулярного выражения содержит RegexOptions.ExplicitCapture флаг или n если параметр применяется к этой подэкспрессии (см . раздел "Параметры группы" далее в этой статье), соответствующий подтекст не фиксируется.

Доступ к захватываемым группам можно получить четырьмя способами:

  • Используя конструкцию обратной ссылки в регулярном выражении. Сопоставленная часть выражения указывается в том же регулярном выражении с помощью синтаксиса \number, где number — это порядковый номер выделенной части выражения.

  • Используя именованную конструкцию обратной ссылки в регулярном выражении. Сопоставленная часть выражения указывается в том же регулярном выражении с помощью синтаксиса \k<name>, где name — это имя захватываемой группы, или \k<number>, где number — это порядковый номер захватываемой группы. Имя захватываемой группы по умолчанию совпадает с ее порядковым номером. Дополнительные сведения см. в разделе Именованные сопоставляемые части выражения далее в этой статье.

  • Используя последовательность замены $number в вызове метода Regex.Replace или Match.Result , где number — это порядковый номер выделенной части выражения.

  • Программным способом, используя объект GroupCollection , возвращаемый свойством Match.Groups . Член коллекции в нулевой позиции представляет все сопоставление регулярного выражения. Каждый последующий член представляет сопоставленную часть выражения. Дополнительные сведения см. в разделе Grouping Constructs and Regular Expression Objects .

В следующем примере показано регулярное выражение, которое определяет повторяющиеся слова в тексте. Две захватываемые группы шаблона регулярного выражения представляют два экземпляра повторяющегося слова. Второй экземпляр выделяется для определения его начальной позиции во входной строке.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"(\w+)\s(\1)\W";
      string input = "He said that that was the the correct answer.";
      foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
         Console.WriteLine("Duplicate '{0}' found at positions {1} and {2}.",
                           match.Groups[1].Value, match.Groups[1].Index, match.Groups[2].Index);
   }
}
// The example displays the following output:
//       Duplicate 'that' found at positions 8 and 13.
//       Duplicate 'the' found at positions 22 and 26.
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "(\w+)\s(\1)\W"
        Dim input As String = "He said that that was the the correct answer."
        For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
            Console.WriteLine("Duplicate '{0}' found at positions {1} and {2}.", _
                              match.Groups(1).Value, match.Groups(1).Index, match.Groups(2).Index)
        Next
    End Sub
End Module
' The example displays the following output:
'       Duplicate 'that' found at positions 8 and 13.
'       Duplicate 'the' found at positions 22 and 26.

Шаблон регулярного выражения выглядит следующим образом:

(\w+)\s(\1)\W

В следующей таблице показано, как интерпретируется шаблон регулярного выражения.

Расписание Description
(\w+) Совпадение с одним или несколькими символами слова. Это первая группа записи.
\s Соответствует пробелу.
(\1) Сопоставление строки в первой захватываемой группе. Это вторая группа записи. Этот пример назначает ее захватываемой группе таким образом, что начальную позицию повторяющегося слова можно извлечь из свойства Match.Index .
\W Сопоставление несловообразующего символа, включая пробел и знак пунктуации. Это не позволяет шаблону регулярного выражения сопоставить слово, которое начинается со слова из первой захватываемой группы.

Именованные сопоставленные части выражения

Следующая конструкция группировки выделяет сопоставленную часть выражения и позволяет получить к ней доступ по имени или номеру:

(?<name>subexpression)

или:

(?'name'subexpression)

Здесь имя является допустимым именем группы, а подтекст является любым допустимым шаблоном регулярного выражения. Параметр name не должен содержать знаки пунктуации и не может начинаться с цифры.

Примечание.

Если параметр RegexOptions метода сопоставления шаблона регулярного выражения содержит флаг RegexOptions.ExplicitCapture или к части выражения применен параметр n (см. Параметры группы далее в этой статье), захват части выражения доступен только через явно именованные группы записи.

Доступ к именованным захватываемым группам можно получить следующими способами:

  • Используя именованную конструкцию обратной ссылки в регулярном выражении. Сопоставленная часть выражения указывается в том же регулярном выражении с помощью синтаксиса \k<name>, где name — это имя захватываемой части выражения.

  • Используя конструкцию обратной ссылки в регулярном выражении. Сопоставленная часть выражения указывается в том же регулярном выражении с помощью синтаксиса \number, где number — это порядковый номер выделенной части выражения. Именованные сопоставленные части выражения нумеруются последовательно слева направо после сопоставленных частей выражения.

  • Используя последовательность замены ${name} в вызове метода Regex.Replace или Match.Result , где name — это имя захватываемой части выражения.

  • Используя последовательность замены $number в вызове метода Regex.Replace или Match.Result , где number — это порядковый номер выделенной части выражения.

  • Программным способом, используя объект GroupCollection , возвращаемый свойством Match.Groups . Член коллекции в нулевой позиции представляет все сопоставление регулярного выражения. Каждый последующий член представляет сопоставленную часть выражения. Именованные захватываемые группы хранятся в коллекции после нумерованных захватываемых групп.

  • Программно, передавая имя части выражения индексатору объекта GroupCollection (в C#) или свойству Item[] (в Visual Basic).

В простом шаблоне регулярного выражения показано, как нумерованные (безымянные) и именованные группы можно указывать программно или с помощью языка регулярных выражений. Регулярное выражение ((?<One>abc)\d+)?(?<Two>xyz)(.*) формирует следующие захватываемые группы по номеру и имени. Первая захватываемая группа (с номером 0) всегда указывает на весь шаблон. (Именованные группы всегда упорядочены в последний раз.)

Номер Имя. Расписание
0 0 (имя по умолчанию) ((?<One>abc)\d+)?(?<Two>xyz)(.*)
1 1 (имя по умолчанию) ((?<One>abc)\d+)
2 2 (имя по умолчанию) (.*)
3 Единица (?<One>abc)
4 Два (?<Two>xyz)

В следующем примере показано регулярное выражение, которое определяет повторяющиеся слова и слова, которые следуют за каждым повторяющимся словом. Шаблон регулярного выражения определяет два именованных вложенных выражения: duplicateWordкоторый представляет дублированное слово и nextWordпредставляет слово, которое следует дублированному слову.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"(?<duplicateWord>\w+)\s\k<duplicateWord>\W(?<nextWord>\w+)";
      string input = "He said that that was the the correct answer.";
      foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
         Console.WriteLine("A duplicate '{0}' at position {1} is followed by '{2}'.",
                           match.Groups["duplicateWord"].Value, match.Groups["duplicateWord"].Index,
                           match.Groups["nextWord"].Value);
   }
}
// The example displays the following output:
//       A duplicate 'that' at position 8 is followed by 'was'.
//       A duplicate 'the' at position 22 is followed by 'correct'.
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "(?<duplicateWord>\w+)\s\k<duplicateWord>\W(?<nextWord>\w+)"
        Dim input As String = "He said that that was the the correct answer."
        Console.WriteLine(Regex.Matches(input, pattern, RegexOptions.IgnoreCase).Count)
        For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
            Console.WriteLine("A duplicate '{0}' at position {1} is followed by '{2}'.", _
                              match.Groups("duplicateWord").Value, match.Groups("duplicateWord").Index, _
                              match.Groups("nextWord").Value)
        Next
    End Sub
End Module
' The example displays the following output:
'    A duplicate 'that' at position 8 is followed by 'was'.
'    A duplicate 'the' at position 22 is followed by 'correct'.

Шаблон регулярного выражения выглядит следующим образом:

(?<duplicateWord>\w+)\s\k<duplicateWord>\W(?<nextWord>\w+)

В следующей таблице показано, как интерпретируется регулярное выражение.

Расписание Description
(?<duplicateWord>\w+) Совпадение с одним или несколькими символами слова. Установка для группы имени duplicateWord.
\s Соответствует пробелу.
\k<duplicateWord> Сопоставление строки из захватываемой группы с именем duplicateWord.
\W Сопоставление несловообразующего символа, включая пробел и знак пунктуации. Это не позволяет шаблону регулярного выражения сопоставить слово, которое начинается со слова из первой захватываемой группы.
(?<nextWord>\w+) Совпадение с одним или несколькими символами слова. Установка для группы имени nextWord.

Имя группы может повторяться в регулярном выражении. Например, можно назвать несколько групп digit, как показано в следующем примере. В случае повторяющихся имен значение объекта Group определяется последней успешной записью во входной строке. Кроме того, коллекция CaptureCollection заполняется сведениями о каждой записи так же, как и в случае, когда имя группы не повторяется.

В примере ниже регулярное выражение \D+(?<digit>\d+)\D+(?<digit>\d+)? включает два вхождения группы с именем digit. Первая группа с именем digit записывает одну или несколько цифр. Вторая группа с именем digit записывает нуль или одно вхождение одной или нескольких цифр. Как видно из выходных данных примера, если вторая захватывающая группа соответствует тексту, этот текст определяет значение объекта Group . Если вторая группа записи не соответствует входной строке, значение последнего успешного совпадения определяет значение Group объекта.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      String pattern = @"\D+(?<digit>\d+)\D+(?<digit>\d+)?";
      String[] inputs = { "abc123def456", "abc123def" };
      foreach (var input in inputs) {
         Match m = Regex.Match(input, pattern);
         if (m.Success) {
            Console.WriteLine("Match: {0}", m.Value);
            for (int grpCtr = 1; grpCtr < m.Groups.Count; grpCtr++) {
               Group grp = m.Groups[grpCtr];
               Console.WriteLine("Group {0}: {1}", grpCtr, grp.Value);
               for (int capCtr = 0; capCtr < grp.Captures.Count; capCtr++)
                  Console.WriteLine("   Capture {0}: {1}", capCtr,
                                    grp.Captures[capCtr].Value);
            }
         }
         else {
            Console.WriteLine("The match failed.");
         }
         Console.WriteLine();
      }
   }
}
// The example displays the following output:
//       Match: abc123def456
//       Group 1: 456
//          Capture 0: 123
//          Capture 1: 456
//
//       Match: abc123def
//       Group 1: 123
//          Capture 0: 123
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "\D+(?<digit>\d+)\D+(?<digit>\d+)?"
        Dim inputs() As String = {"abc123def456", "abc123def"}
        For Each input As String In inputs
            Dim m As Match = Regex.Match(input, pattern)
            If m.Success Then
                Console.WriteLine("Match: {0}", m.Value)
                For grpCtr As Integer = 1 to m.Groups.Count - 1
                    Dim grp As Group = m.Groups(grpCtr)
                    Console.WriteLine("Group {0}: {1}", grpCtr, grp.Value)
                    For capCtr As Integer = 0 To grp.Captures.Count - 1
                        Console.WriteLine("   Capture {0}: {1}", capCtr,
                                          grp.Captures(capCtr).Value)
                    Next
                Next
            Else
                Console.WriteLine("The match failed.")
            End If
            Console.WriteLine()
        Next
    End Sub
End Module
' The example displays the following output:
'       Match: abc123def456
'       Group 1: 456
'          Capture 0: 123
'          Capture 1: 456
'
'       Match: abc123def
'       Group 1: 123
'          Capture 0: 123

В следующей таблице показано, как интерпретируется регулярное выражение.

Расписание Description
\D+ Совпадение с одной или несколькими недесятичными цифрами.
(?<digit>\d+) Совпадение с одной или несколькими десятичными цифрами. Назначение соответствия для группы с именем digit .
\D+ Совпадение с одной или несколькими недесятичными цифрами.
(?<digit>\d+)? Совпадение с нулем или одним вхождением одной или нескольких десятичных цифр. Назначение соответствия для группы с именем digit .

Сбалансированные определения группы

Сбалансированное определение группы удаляет определение ранее заданной группы и сохраняет в текущей группе интервал между предыдущей и текущей группами. Конструкция группировки использует следующий формат:

(?<name1-name2>subexpression)

или:

(?'name1-name2' subexpression)

Здесь имя1 — это текущая группа (необязательно), name2 — это ранее определенная группа, а подэкспрессия — это любой допустимый шаблон регулярного выражения. Это сбалансированное определение группы удаляет определение name2 и сохраняет интервал между name2 и name1 в name1. Если группа name2 не определена, для соответствия выполняется обратный поиск. Так как удаление последнего определения name2 предоставляет доступ к предыдущему определению name2, эта конструкция позволяет использовать стек выделений для группы name2 в качестве счетчика вложенных конструкций, например круглых скобок или открывающих и закрывающих квадратных скобок.

Сбалансированное определение группы использует в качестве стека name2 . Начальный символ каждой вложенной конструкции размещается в группе и в коллекции Group.Captures . При сопоставлении закрывающего символа соответствующий открывающий символ удаляется из группы, а коллекция Captures уменьшается на один элемент. После сопоставления открывающих и закрывающих символов всех вложенных конструкций, группа name2 оказывается пустой.

Примечание.

Если изменить регулярное выражение в следующем примере для использования соответствующего открывающего и закрывающего символа вложенной конструкции, вы сможете использовать его для обработки большинства вложенных конструкций, таких как математические выражения или строки программного кода, которые могут содержать множества вложенных вызовов методов.

В следующем примере для сопоставления левых и правых угловых квадратных скобок (<>) в входной строке используется определение группы балансировки. В примере определены две именованные группы, Open и Close, которые используются как стек для отслеживания соответствующих пар угловых скобок. Каждая выделенная левая угловая скобка помещается в коллекцию группы Open , а каждая выделенная правая угловая скобка помещается в коллекцию группы Close . Сбалансированное определение группы позволяет убедиться, что для каждой левой угловой скобки существует соответствующая правая угловая скобка. В противном случае последний подшаблон, (?(Open)(?!)), вычисляется, только если группа Open не пуста (следовательно, все вложенные конструкции не закрыты). Если последний подшаблон вычисляется, сопоставление вызывает ошибку, так как подшаблон (?!) является утверждением отрицательного поиска вперед нулевой ширины, которое всегда возвращает ошибку.

using System;
using System.Text.RegularExpressions;

class Example
{
   public static void Main()
   {
      string pattern = "^[^<>]*" +
                       "(" +
                       "((?'Open'<)[^<>]*)+" +
                       "((?'Close-Open'>)[^<>]*)+" +
                       ")*" +
                       "(?(Open)(?!))$";
      string input = "<abc><mno<xyz>>";

      Match m = Regex.Match(input, pattern);
      if (m.Success == true)
      {
         Console.WriteLine("Input: \"{0}\" \nMatch: \"{1}\"", input, m);
         int grpCtr = 0;
         foreach (Group grp in m.Groups)
         {
            Console.WriteLine("   Group {0}: {1}", grpCtr, grp.Value);
            grpCtr++;
            int capCtr = 0;
            foreach (Capture cap in grp.Captures)
            {
                Console.WriteLine("      Capture {0}: {1}", capCtr, cap.Value);
                capCtr++;
            }
          }
      }
      else
      {
         Console.WriteLine("Match failed.");
      }
    }
}
// The example displays the following output:
//    Input: "<abc><mno<xyz>>"
//    Match: "<abc><mno<xyz>>"
//       Group 0: <abc><mno<xyz>>
//          Capture 0: <abc><mno<xyz>>
//       Group 1: <mno<xyz>>
//          Capture 0: <abc>
//          Capture 1: <mno<xyz>>
//       Group 2: <xyz
//          Capture 0: <abc
//          Capture 1: <mno
//          Capture 2: <xyz
//       Group 3: >
//          Capture 0: >
//          Capture 1: >
//          Capture 2: >
//       Group 4:
//       Group 5: mno<xyz>
//          Capture 0: abc
//          Capture 1: xyz
//          Capture 2: mno<xyz>
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "^[^<>]*" & _
                                "(" + "((?'Open'<)[^<>]*)+" & _
                                "((?'Close-Open'>)[^<>]*)+" + ")*" & _
                                "(?(Open)(?!))$"
        Dim input As String = "<abc><mno<xyz>>"
        Dim rgx AS New Regex(pattern) '
        Dim m As Match = Regex.Match(input, pattern)
        If m.Success Then
            Console.WriteLine("Input: ""{0}"" " & vbCrLf & "Match: ""{1}""", _
                               input, m)
            Dim grpCtr As Integer = 0
            For Each grp As Group In m.Groups
                Console.WriteLine("   Group {0}: {1}", grpCtr, grp.Value)
                grpCtr += 1
                Dim capCtr As Integer = 0
                For Each cap As Capture In grp.Captures
                    Console.WriteLine("      Capture {0}: {1}", capCtr, cap.Value)
                    capCtr += 1
                Next
            Next
        Else
            Console.WriteLine("Match failed.")
        End If
    End Sub
End Module
' The example displays the following output:
'       Input: "<abc><mno<xyz>>"
'       Match: "<abc><mno<xyz>>"
'          Group 0: <abc><mno<xyz>>
'             Capture 0: <abc><mno<xyz>>
'          Group 1: <mno<xyz>>
'             Capture 0: <abc>
'             Capture 1: <mno<xyz>>
'          Group 2: <xyz
'             Capture 0: <abc
'             Capture 1: <mno
'             Capture 2: <xyz
'          Group 3: >
'             Capture 0: >
'             Capture 1: >
'             Capture 2: >
'          Group 4:
'          Group 5: mno<xyz>
'             Capture 0: abc
'             Capture 1: xyz
'             Capture 2: mno<xyz>

Шаблон регулярного выражения выглядит следующим образом:

^[^<>]*(((?'Open'<)[^<>]*)+((?'Close-Open'>)[^<>]*)+)*(?(Open)(?!))$

Регулярное выражение интерпретируется следующим образом:

Расписание Description
^ Начало с первого символа строки.
[^<>]* Сопоставление нуля или большего числа символов, которые не являются правой или левой угловой скобкой.
(?'Open'<) Сопоставление левой угловой скобки и ее назначение группе Open.
[^<>]* Сопоставление нуля или большего числа символов, которые не являются правой или левой угловой скобкой.
((?'Open'<)[^<>]*)+ Сопоставление одного или нескольких вхождений левой угловой скобки, за которой следует ноль или больше символов, не являющихся левой или правой угловой скобкой. Это вторая группа записи.
(?'Close-Open'>) Сопоставление правой угловой скобки, назначение подстроки между группой Open и текущей группой группе Close и удаление определения группы Open .
[^<>]* Сопоставление нуля или большего числа вхождений любого символа, не являющегося левой или правой угловой скобкой.
((?'Close-Open'>)[^<>]*)+ Сопоставление одного или нескольких вхождений правой угловой скобки, за которой следует ноль или больше символов, не являющихся левой или правой угловой скобкой. При сопоставлении правой угловой скобки подстрока между группой Open и текущей группой назначается группе Close , а определение группы Open удаляется. Это третья группа записи.
(((?'Open'<)[^<>]*)+((?'Close-Open'>)[^<>]*)+)* Сопоставление нуля или большего числа вхождений следующего шаблона: одно или несколько вхождений левой угловой скобки, за которой следуют ноль или большее число символов, отличных от угловых скобок, одно или несколько вхождений правой угловой скобки и ноль или большее число символов, отличных от угловых скобок. При сопоставлении правой угловой скобки определение группы Open удаляется, а подстрока между группой Open и текущей группой назначается группе Close . Это первая группа записи.
(?(Open)(?!)) Если группа Open существует, поиск совпадения прекращается, если возможно сопоставление пустой строки, но позиция механизма регулярных выражений в строке не изменяется. Это утверждение отрицательного просмотра вперед нулевой ширины. Так как пустая строка всегда неявно присутствует во входной строке, это сопоставление всегда возвращает ошибку. Ошибка этого сопоставления указывает на то, что угловые скобки не сбалансированы.
$ Соответствует концу входной строки.

Последняя часть выражения, (?(Open)(?!)), указывает, правильно ли сбалансированы вложенные конструкции во входной строке (например, существует ли для каждой левой угловой скобки соответствующая правая угловая скобка). В ней используется условное сопоставление на основе действительной захватываемой группы. Дополнительные сведения см. в разделе Конструкции изменения в регулярных выражениях. Если группа Open определена, механизм регулярных выражений пытается сопоставить часть выражения (?!) во входной строке. Группа Open должна быть определена, только если вложенные конструкции не сбалансированы. Поэтому шаблон для сопоставления во входной строке должен всегда вызывать ошибку соответствия. В этом случае (?!) — это утверждение отрицательного просмотра вперед нулевой ширины, которое всегда вызывает ошибку, так как пустая строка всегда неявно присутствует в следующей позиции во входной строке.

В примере обработчик регулярных выражений оценивает входную строку abc<>< mno<xyz>>, как показано в следующей таблице.

Этап Расписание Результат
1 ^ Начало соответствия в начале входной строки.
2 [^<>]* Поиск символов, отличных от угловых скобок, до левой угловой скобки. Совпадения не найдены.
3 (((?'Open'<) Соответствует левой угловой скобке в< abc> и назначает ее Open группе.
4 [^<>]* Сопоставляется строка "abc".
5 )+ "<abc" — это значение второй захваченной группы.

Следующий символ во входной строке не является левой угловой скобкой, поэтому механизм регулярных выражений не возвращается к подшаблону (?'Open'<)[^<>]*).
6 ((?'Close-Open'>) Соответствует правой угловой скобке в< "abc", назначает "abc>", которая является подстрокой между Open группой и правой угловой скобкой, Close в группу и удаляет текущее значение ("<") Open группы, оставляя его пустым.
7 [^<>]* Поиск символов, отличных от угловых скобок, после правой угловой скобки. Совпадения не найдены.
8 )+ Значение третьей захваченной группы — ">".

Следующий символ во входной строке не является правой угловой скобкой, поэтому механизм регулярных выражений не возвращается к подшаблону ((?'Close-Open'>)[^<>]*) .
9 )* Значение первой захваченной группы —< abc>.

Следующий символ во входной строке является левой угловой скобкой, поэтому механизм регулярных выражений возвращается к подшаблону (((?'Open'<) .
10 (((?'Open'<) Сопоставляет левую угловую скобку в строке "<mno" и назначает ее группе Open. Теперь его Group.Captures коллекция имеет одно значение "<".
11 [^<>]* Сопоставляется подстрока "mno".
12 )+ "<mno" — это значение второй захваченной группы.

Следующий символ во входной строке является левой угловой скобкой, поэтому механизм регулярных выражений возвращается к подшаблону (?'Open'<)[^<>]*) .
13 (((?'Open'<) Соответствует левой угловой скобке в xyz<> и назначает ее Open группе. Коллекция Group.Captures группы теперь включает два захвата: левую угловую скобку из< "mno" и левую угловую скобку из xyz<>.Open
14 [^<>]* Сопоставляется подстрока "xyz".
15 )+ "<xyz" — это значение второй захваченной группы.

Следующий символ во входной строке не является левой угловой скобкой, поэтому механизм регулярных выражений не возвращается к подшаблону (?'Open'<)[^<>]*).
16 ((?'Close-Open'>) Соответствует правой угловой скобке в xyz<>. "xyz" задает подстроку между группой Open и правой угловой скобкой группы Close и удаляет текущее значение группы Open . Значение предыдущего захвата (левая угловая скобка из "<mno") становится текущим значением группы Open. Коллекция Captures группы теперь включает в себя один захват, левую угловую скобку из xyz<>.Open
17 [^<>]* Поиск символов, отличных от угловых скобок. Совпадения не найдены.
18 )+ Значение третьей захваченной группы — ">".

Следующий символ во входной строке является правой угловой скобкой, поэтому механизм регулярных выражений возвращается к подшаблону ((?'Close-Open'>)[^<>]*) .
19 ((?'Close-Open'>) Соответствует окончательной правой угловой скобке в xyz, назначает "mno xyz>>>" (подстроку между Open группой и правой угловой скобкой) Close группе и удаляет текущее значение Open группы.< Теперь группа Open пуста.
20 [^<>]* Поиск символов, отличных от угловых скобок. Совпадения не найдены.
21 )+ Значение третьей захваченной группы — ">".

Следующий символ во входной строке не является правой угловой скобкой, поэтому механизм регулярных выражений не возвращается к подшаблону ((?'Close-Open'>)[^<>]*) .
22 )* Значение первой захваченной группы —< mno<xyz>>.

Следующий символ во входной строке не является левой угловой скобкой, поэтому механизм регулярных выражений не возвращается к подшаблону (((?'Open'<).
23 (?(Open)(?!)) Группа Open не определена, поиск соответствий не выполняется.
24 $ Сопоставление конца входной строки.

Незахватываемые группы

Следующая конструкция группирования не фиксирует подстроку, которая соответствует подтексту:

(?:subexpression)

Здесь подэкспрессия является любым допустимым шаблоном регулярного выражения. Незахватываемая конструкция группировки обычно используется, если к группе применяется квантификатор, но подстроки, выделенные группой, не представляют интереса.

Примечание.

Если регулярное выражение содержит вложенные конструкции группировки, внешняя незахватываемая конструкция группировки не применяется к внутренним вложенным конструкциям группировки.

В следующем примере показано регулярное выражение, содержащее незахватываемые группы. Обратите внимание, что результат не содержит захватываемые группы.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"(?:\b(?:\w+)\W*)+\.";
      string input = "This is a short sentence.";
      Match match = Regex.Match(input, pattern);
      Console.WriteLine("Match: {0}", match.Value);
      for (int ctr = 1; ctr < match.Groups.Count; ctr++)
         Console.WriteLine("   Group {0}: {1}", ctr, match.Groups[ctr].Value);
   }
}
// The example displays the following output:
//       Match: This is a short sentence.
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "(?:\b(?:\w+)\W*)+\."
        Dim input As String = "This is a short sentence."
        Dim match As Match = Regex.Match(input, pattern)
        Console.WriteLine("Match: {0}", match.Value)
        For ctr As Integer = 1 To match.Groups.Count - 1
            Console.WriteLine("   Group {0}: {1}", ctr, match.Groups(ctr).Value)
        Next
    End Sub
End Module
' The example displays the following output:
'       Match: This is a short sentence.

Регулярное выражение (?:\b(?:\w+)\W*)+\. сопоставляет предложение, которое заканчивается точкой. Так как оно ищет предложения, а не отдельные слова, конструкции группировки используются только как квантификаторы. Возможные интерпретации шаблона регулярного выражения показаны в следующей таблице.

Расписание Description
\b Совпадение должно начинаться на границе слова.
(?:\w+) Совпадение с одним или несколькими символами слова. Сопоставленные текст не назначается захватываемой группе.
\W* Совпадение с нулем или большим числом несловообразующих символов.
(?:\b(?:\w+)\W*)+ Совпадение шаблона с одним или несколькими словообразующими символами начиная с границы слова, за которыми следует ноль и более несловообразующих символов, один или более раз. Сопоставленные текст не назначается захватываемой группе.
\. Сопоставляется точка.

Параметры группы

Следующая конструкция группировки применяет или отключает указанные параметры в части выражения:

(?imnsx-imnsx: subexpression )

Здесь подэкспрессия является любым допустимым шаблоном регулярного выражения. Например, (?i-s:) отключает учет регистра и однострочный режим. Дополнительные сведения о доступных встроенных параметрах см. в разделе Параметры регулярных выражений.

Примечание.

Вы можете указать параметры, которые применяются ко всему регулярному выражению, а не его части, используя конструктор класса System.Text.RegularExpressions.Regex или статичный метод. Также можно указать встроенные параметры, которые применяются после определенной точки в регулярном выражении с использованием языковой конструкции (?imnsx-imnsx) .

Конструкция параметров группы не является захватываемой группой. Это значит, что несмотря на то, что любая часть строки, захватываемая частью выражения , включается в соответствие, она не добавляется в захватываемую группу и не используется для заполнения объекта GroupCollection .

Например, регулярное выражение \b(?ix: d \w+)\s в следующем примере использует встроенные параметры в конструкции группировки, чтобы включить сопоставление без учета регистра и игнорировать пробелы при определении слов, начинающихся с буквы "d". Определение регулярного выражения показано в следующей таблице.

Расписание Description
\b Совпадение должно начинаться на границе слова.
(?ix: d \w+) Выполняется сопоставление буквы "d", за которой следует один или более словообразующих символов без учета регистра, пробелы в шаблоне пропускаются.
\s Соответствует пробелу.
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.      

Утверждения положительного просмотра вперед нулевой ширины

Следующая конструкция группировки определяет утверждение положительного просмотра вперед нулевой ширины:

(?= subexpression )

Здесь подэкспрессия — это любой шаблон регулярного выражения. Для успешного сопоставления входная строка должна соответствовать шаблону регулярного выражения в части выражения, хотя сопоставленная подстрока не включается в результат сопоставления. Утверждение положительного просмотра вперед нулевой ширины не выполняет обратный поиск.

Обычно утверждение положительного просмотра вперед нулевой ширины находится в конце шаблона регулярного выражения. Оно определяет подстроку, которую необходимо найти в конце строки для сопоставления, но которая не включается в сопоставление. Это также полезно для предотвращения излишнего обратного поиска. Утверждение положительного просмотра вперед нулевой ширины можно использовать, чтобы определенная захватываемая группа начиналась с текста, соответствующего подмножеству шаблона, заданного для этой группы. Например, если захватываемая группа соответствует последовательным словообразующим символом, вы можете использовать утверждение положительного просмотра вперед нулевой ширины, чтобы указать, что первый символ должен быть прописной буквой.

Следующий пример использует утверждение положительного просмотра вперед нулевой ширины для сопоставления слова, которое идет перед глаголом "is" во входной строке.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"\b\w+(?=\sis\b)";
      string[] inputs = { "The dog is a Malamute.",
                          "The island has beautiful birds.",
                          "The pitch missed home plate.",
                          "Sunday is a weekend day." };

      foreach (string input in inputs)
      {
         Match match = Regex.Match(input, pattern);
         if (match.Success)
            Console.WriteLine("'{0}' precedes 'is'.", match.Value);
         else
            Console.WriteLine("'{0}' does not match the pattern.", input);
      }
   }
}
// The example displays the following output:
//    'dog' precedes 'is'.
//    'The island has beautiful birds.' does not match the pattern.
//    'The pitch missed home plate.' does not match the pattern.
//    'Sunday' precedes 'is'.
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "\b\w+(?=\sis\b)"
        Dim inputs() As String = {"The dog is a Malamute.", _
                                   "The island has beautiful birds.", _
                                   "The pitch missed home plate.", _
                                   "Sunday is a weekend day."}

        For Each input As String In inputs
            Dim match As Match = Regex.Match(input, pattern)
            If match.Success Then
                Console.WriteLine("'{0}' precedes 'is'.", match.Value)
            Else
                Console.WriteLine("'{0}' does not match the pattern.", input)
            End If
        Next
    End Sub
End Module
' The example displays the following output:
'       'dog' precedes 'is'.
'       'The island has beautiful birds.' does not match the pattern.
'       'The pitch missed home plate.' does not match the pattern.
'       'Sunday' precedes 'is'.

Возможные интерпретации регулярного выражения \b\w+(?=\sis\b) показаны в следующей таблице.

Расписание Description
\b Совпадение должно начинаться на границе слова.
\w+ Совпадение с одним или несколькими символами слова.
(?=\sis\b) Определяется, следуют ли за словообразующими словами пробел и строка "is", которая оканчивается на границе слова. Если это так, совпадение успешно.

Утверждения отрицательного просмотра вперед нулевой ширины

Следующая конструкция группировки определяет утверждение отрицательного просмотра вперед нулевой ширины:

(?! subexpression )

Здесь подэкспрессия — это любой шаблон регулярного выражения. Для успешного сопоставления входная строка не должна соответствовать шаблону регулярного выражения в части выражения, хотя сопоставленная подстрока не включается в результат сопоставления.

Утверждение отрицательного просмотра вперед нулевой ширины обычно используется в начале или в конце регулярного выражения. В начале регулярного выражения оно может определить шаблон, для которого не должно быть совпадения, когда в начале регулярного выражения определен похожий, но более общий шаблон для сопоставления. В этом случае утверждение часто используется для ограничения обратного поиска. В конце регулярного выражения утверждение может определять часть выражения, которое не должно присутствовать в конце совпадения.

В следующем примере определяется регулярное выражение, использующее утверждение просмотра вперед нулевой ширины в начале регулярного выражения для сопоставления слов, которые не начинаются на "un".

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"\b(?!un)\w+\b";
      string input = "unite one unethical ethics use untie ultimate";
      foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnoreCase))
         Console.WriteLine(match.Value);
   }
}
// The example displays the following output:
//       one
//       ethics
//       use
//       ultimate
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "\b(?!un)\w+\b"
        Dim input As String = "unite one unethical ethics use untie ultimate"
        For Each match As Match In Regex.Matches(input, pattern, RegexOptions.IgnoreCase)
            Console.WriteLine(match.Value)
        Next
    End Sub
End Module
' The example displays the following output:
'       one
'       ethics
'       use
'       ultimate

Возможные интерпретации регулярного выражения \b(?!un)\w+\b показаны в следующей таблице.

Расписание Description
\b Совпадение должно начинаться на границе слова.
(?!un) Определяется, являются ли два следующих символа "un". Если это не так, сопоставление возможно.
\w+ Совпадение с одним или несколькими символами слова.
\b Совпадение должно заканчиваться на границе слова.

В следующем примере определяется регулярное выражение, использующее утверждение просмотра вперед нулевой ширины в конце регулярного выражения для сопоставления слов, которые не начинаются на знак пунктуации.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"\b\w+\b(?!\p{P})";
      string input = "Disconnected, disjointed thoughts in a sentence fragment.";
      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine(match.Value);
   }
}
// The example displays the following output:
//       disjointed
//       thoughts
//       in
//       a
//       sentence
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "\b\w+\b(?!\p{P})"
        Dim input As String = "Disconnected, disjointed thoughts in a sentence fragment."
        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:
'       disjointed
'       thoughts
'       in
'       a
'       sentence

Возможные интерпретации регулярного выражения \b\w+\b(?!\p{P}) показаны в следующей таблице.

Расписание Description
\b Совпадение должно начинаться на границе слова.
\w+ Совпадение с одним или несколькими символами слова.
\b Совпадение должно заканчиваться на границе слова.
\p{P}) Если следующий символ — не знак пунктуации (например, точка или запятая), сопоставление выполняется успешно.

Утверждения положительного просмотра назад нулевой ширины

Следующая конструкция группировки определяет утверждение положительного просмотра назад нулевой ширины:

(?<= subexpression )

Здесь подэкспрессия — это любой шаблон регулярного выражения. Для успешного сопоставления часть выражения должна содержаться во входной строке слева от текущей позиции, хотя subexpression не включается в результат. Утверждение положительного просмотра назад нулевой ширины не выполняет обратный поиск.

Утверждения положительного просмотра назад нулевой ширины обычно используются в начале регулярных выражений. Определяемый ими шаблон — это предварительное условие сопоставления, но не часть результата сопоставления.

Например, следующий пример сопоставляет две последних цифры года для 21-го века (т. е. сопоставляемой строке должны предшествовать цифры "20").

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string input = "2010 1999 1861 2140 2009";
      string pattern = @"(?<=\b20)\d{2}\b";

      foreach (Match match in Regex.Matches(input, pattern))
         Console.WriteLine(match.Value);
   }
}
// The example displays the following output:
//       10
//       09
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim input As String = "2010 1999 1861 2140 2009"
        Dim pattern As String = "(?<=\b20)\d{2}\b"

        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:
'       10
'       09

Возможные интерпретации шаблона регулярного выражения (?<=\b20)\d{2}\b показаны в следующей таблице.

Расписание Description
\d{2} Совпадение с двумя десятичными цифрами.
(?<=\b20) Сопоставление продолжается, если двум десятичным цифрам предшествуют десятичные цифры "20" на границе слова.
\b Совпадение должно заканчиваться на границе слова.

Утверждения положительного просмотра назад нулевой ширины также используются для ограничения обратного поиска, если последний символ или символы в захватываемой группе должны быть подмножеством символов, соответствующих шаблону регулярного выражения. Например, если группа захватывает все последовательные словообразующие символы, вы можете использовать утверждение положительного просмотра назад нулевой ширины, чтобы указать, что последний символ должен быть буквой.

Утверждения отрицательного просмотра назад нулевой ширины

Следующая конструкция группировки определяет утверждение отрицательного просмотра назад нулевой ширины:

(?<! subexpression )

Здесь подэкспрессия — это любой шаблон регулярного выражения. Для успешного сопоставления часть выражения не должна находиться во входной строке слева от текущей позиции. Однако любая подстрока, не соответствующая subexpression , не включается в результат сопоставления.

Утверждения отрицательного просмотра назад нулевой ширины обычно используются в начале регулярных выражений. Определяемый ими шаблон препятствует сопоставлению в последующей строке. Они также используются для ограничения обратного поиска, если последний символ или символы в захватываемой группе не должны соответствовать одному или нескольким символам, соответствующим шаблону регулярного выражения группы. Например, если группа захватывает все последовательные словообразующие символы, вы можете использовать утверждение отрицательного просмотра назад нулевой ширины, чтобы указать, что последний символ не должен быть символом подчеркивания (_).

Следующий пример сопоставляет дату каждого дня буднего недели (т. е. не субботы или воскресенья).

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string[] dates = { "Monday February 1, 2010",
                         "Wednesday February 3, 2010",
                         "Saturday February 6, 2010",
                         "Sunday February 7, 2010",
                         "Monday, February 8, 2010" };
      string pattern = @"(?<!(Saturday|Sunday) )\b\w+ \d{1,2}, \d{4}\b";

      foreach (string dateValue in dates)
      {
         Match match = Regex.Match(dateValue, pattern);
         if (match.Success)
            Console.WriteLine(match.Value);
      }
   }
}
// The example displays the following output:
//       February 1, 2010
//       February 3, 2010
//       February 8, 2010
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim dates() As String = {"Monday February 1, 2010", _
                                  "Wednesday February 3, 2010", _
                                  "Saturday February 6, 2010", _
                                  "Sunday February 7, 2010", _
                                  "Monday, February 8, 2010"}
        Dim pattern As String = "(?<!(Saturday|Sunday) )\b\w+ \d{1,2}, \d{4}\b"

        For Each dateValue As String In dates
            Dim match As Match = Regex.Match(dateValue, pattern)
            If match.Success Then
                Console.WriteLine(match.Value)
            End If
        Next
    End Sub
End Module
' The example displays the following output:
'       February 1, 2010
'       February 3, 2010
'       February 8, 2010

Возможные интерпретации шаблона регулярного выражения (?<!(Saturday|Sunday) )\b\w+ \d{1,2}, \d{4}\b показаны в следующей таблице.

Расписание Description
\b Совпадение должно начинаться на границе слова.
\w+ Сопоставляется один или несколько словообразующих символов, за которыми следует пробел.
\d{1,2}, Сопоставляется одна или две десятичные цифры, за которыми следует пробел и запятая.
\d{4}\b Сопоставляются 4 десятичные цифры, сопоставление прекращается на границе слова.
(?<!(Saturday|Sunday) ) Если сопоставлению предшествуют строки, отличные от "Saturday" или "Sunday", за которыми следует пробел, сопоставление выполняется успешно.

Атомарные группы

Следующая конструкция группировки представляет атомарную группу (в некоторых других обработчиках регулярных выражений называемую частью выражения без обратного отслеживания, атомарной частью выражения или однократной частью выражения):

(?> subexpression )

Здесь подэкспрессия — это любой шаблон регулярного выражения.

Обычно, если регулярное выражение содержит необязательный или альтернативный шаблон сопоставления, а сопоставление завершается неудачно, механизм регулярных выражений может разветвляться по разным направлениям для сопоставления входной строки с шаблоном. Если сопоставление не найдено в первой ветви, механизм регулярных выражений может вернуться к точке, где было найдено первое сопоставление и повторить попытку во второй ветви. Этот процесс может продолжаться, пока не будут обойдены все ветви.

Группа (?>часть выражения) отключает обратное отслеживание. Механизм регулярных выражений сопоставляет максимально возможное число символов во входной строке. Если дальнейшее сопоставление невозможно, обратный поиск для применения альтернативных шаблонов не выполняется. (Т. е. часть выражения сопоставляет только строки, которые могут быть сопоставлены только частью выражения, попытка сопоставить строку на основе этой и последующих частей выражения не осуществляется.)

Этот вариант рекомендуется, если вы знаете, что обратный поиск не даст результатов. Если запретить механизму регулярных выражений выполнять ненужные операции поиска, производительность станет выше.

В следующем примере показано, как атомарная группа изменяет результаты сопоставления шаблона. Возвращающееся регулярное выражение успешно сопоставляет ряд повторяющихся символов, за которыми следует один или более экземпляров того же символа на границе слова, а невозвращающееся регулярное выражение — нет.

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string[] inputs = { "cccd.", "aaad", "aaaa" };
      string back = @"(\w)\1+.\b";
      string noback = @"(?>(\w)\1+).\b";

      foreach (string input in inputs)
      {
         Match match1 = Regex.Match(input, back);
         Match match2 = Regex.Match(input, noback);
         Console.WriteLine("{0}: ", input);

         Console.Write("   Backtracking : ");
         if (match1.Success)
            Console.WriteLine(match1.Value);
         else
            Console.WriteLine("No match");

         Console.Write("   Nonbacktracking: ");
         if (match2.Success)
            Console.WriteLine(match2.Value);
         else
            Console.WriteLine("No match");
      }
   }
}
// The example displays the following output:
//    cccd.:
//       Backtracking : cccd
//       Nonbacktracking: cccd
//    aaad:
//       Backtracking : aaad
//       Nonbacktracking: aaad
//    aaaa:
//       Backtracking : aaaa
//       Nonbacktracking: No match
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim inputs() As String = {"cccd.", "aaad", "aaaa"}
        Dim back As String = "(\w)\1+.\b"
        Dim noback As String = "(?>(\w)\1+).\b"

        For Each input As String In inputs
            Dim match1 As Match = Regex.Match(input, back)
            Dim match2 As Match = Regex.Match(input, noback)
            Console.WriteLine("{0}: ", input)

            Console.Write("   Backtracking : ")
            If match1.Success Then
                Console.WriteLine(match1.Value)
            Else
                Console.WriteLine("No match")
            End If

            Console.Write("   Nonbacktracking: ")
            If match2.Success Then
                Console.WriteLine(match2.Value)
            Else
                Console.WriteLine("No match")
            End If
        Next
    End Sub
End Module
' The example displays the following output:
'    cccd.:
'       Backtracking : cccd
'       Nonbacktracking: cccd
'    aaad:
'       Backtracking : aaad
'       Nonbacktracking: aaad
'    aaaa:
'       Backtracking : aaaa
'       Nonbacktracking: No match

Определение невозвращающегося регулярного выражения (?>(\w)\1+).\b показано в следующей таблице.

Расписание Description
(\w) Сопоставляется один словообразующий символ, который назначается первой захватываемой группе.
\1+ Значение первой захваченной подстроки сопоставляется один или несколько раз.
. Сопоставляется любой символ.
\b Сопоставление заканчивается на границе слова.
(?>(\w)\1+) Соответствует одному или нескольким вхождениям повторяющегося символа слова, но не вернитесь к последнему символу на границе слова.

Конструкции группировки и объекты регулярных выражений

Подстроки, сопоставляемые захватываемой группой регулярного выражения, представлены объектами System.Text.RegularExpressions.Group , которые можно извлечь из объекта System.Text.RegularExpressions.GroupCollection , возвращаемого свойством Match.Groups . Объект GroupCollection заполняется следующим образом:

  • Первый объект Group в коллекции (объект с нулевым индексом) представляет все сопоставление.
  • Следующий набор объектов Group представляет неименованные (нумерованные) захватываемые группы. Они указываются в том порядке, в котором они определены в регулярном выражении, слева направо. Значения индекса этих групп лежат в диапазоне от 1 до числа неименованных захватываемых групп в коллекции. (Индекс конкретной группы эквивалентен нумерованному обратному ссылок. Дополнительные сведения о обратных ссылках см. в разделе "Конструкции backreference".)
  • Последний набор объектов Group представляет именованные захватываемые группы. Они указываются в том порядке, в котором они определены в регулярном выражении, слева направо. Значение индекса первой именованной захватываемой группы на единицу больше индекса, последней неименованной захватываемой группы. Если в регулярном выражении нет неименованных захватываемых групп, индекс первой именованной захватываемой группы равен единице.

Если к захватываемой группе применяется квантификатор, соответствующие свойства Group , Capture.Valueи Capture.Indexобъекта Capture.Length отражают последнюю подстроку, выделяемую захватываемой группой. Вы можете получить полный набор подстрок, выделяемые группами с квантификаторами, из объекта CaptureCollection , возвращаемого свойством Group.Captures .

В следующем примере показана связь между объектами Group и Capture .

using System;
using System.Text.RegularExpressions;

public class Example
{
   public static void Main()
   {
      string pattern = @"(\b(\w+)\W+)+";
      string input = "This is a short sentence.";
      Match match = Regex.Match(input, pattern);
      Console.WriteLine("Match: '{0}'", match.Value);
      for (int ctr = 1; ctr < match.Groups.Count; ctr++)
      {
         Console.WriteLine("   Group {0}: '{1}'", ctr, match.Groups[ctr].Value);
         int capCtr = 0;
         foreach (Capture capture in match.Groups[ctr].Captures)
         {
            Console.WriteLine("      Capture {0}: '{1}'", capCtr, capture.Value);
            capCtr++;
         }
      }
   }
}
// The example displays the following output:
//       Match: 'This is a short sentence.'
//          Group 1: 'sentence.'
//             Capture 0: 'This '
//             Capture 1: 'is '
//             Capture 2: 'a '
//             Capture 3: 'short '
//             Capture 4: 'sentence.'
//          Group 2: 'sentence'
//             Capture 0: 'This'
//             Capture 1: 'is'
//             Capture 2: 'a'
//             Capture 3: 'short'
//             Capture 4: 'sentence'
Imports System.Text.RegularExpressions

Module Example
    Public Sub Main()
        Dim pattern As String = "(\b(\w+)\W+)+"
        Dim input As String = "This is a short sentence."
        Dim match As Match = Regex.Match(input, pattern)
        Console.WriteLine("Match: '{0}'", match.Value)
        For ctr As Integer = 1 To match.Groups.Count - 1
            Console.WriteLine("   Group {0}: '{1}'", ctr, match.Groups(ctr).Value)
            Dim capCtr As Integer = 0
            For Each capture As Capture In match.Groups(ctr).Captures
                Console.WriteLine("      Capture {0}: '{1}'", capCtr, capture.Value)
                capCtr += 1
            Next
        Next
    End Sub
End Module
' The example displays the following output:
'       Match: 'This is a short sentence.'
'          Group 1: 'sentence.'
'             Capture 0: 'This '
'             Capture 1: 'is '
'             Capture 2: 'a '
'             Capture 3: 'short '
'             Capture 4: 'sentence.'
'          Group 2: 'sentence'
'             Capture 0: 'This'
'             Capture 1: 'is'
'             Capture 2: 'a'
'             Capture 3: 'short'
'             Capture 4: 'sentence'

Шаблон регулярного выражения (\b(\w+)\W+)+ извлекает отдельные слова из строки. Определяется, как показано в следующей таблице.

Расписание Description
\b Совпадение должно начинаться на границе слова.
(\w+) Совпадение с одним или несколькими символами слова. Вместе эти символы формируют слово. Это вторая группа записи.
\W+ Совпадение с одним или большим числом несловообразующих символов.
(\b(\w+)\W+) Шаблон из одного или нескольких словообразующих символов, за которыми следует ноль или несколько словообразующих слов, выделяется один или несколько раз. Это первая группа записи.

Вторая группа сопоставляет каждое слово предложения. Первая группа сопоставляет каждое слово вместе со знаками пунктуации и пробелом после слова. Объект Group с индексом 2 предоставляет сведения о тексте, сопоставленном второй группой. Полный набор слов, выделенных захватываемой группой, доступен в объекте CaptureCollection , который возвращается свойством Group.Captures .

См. также