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


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

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

  • Соответствует подэкспрессии, повторяющейся в входной строке.
  • Примените квантификатор к подвыражению, содержащему несколько языковых элементов регулярных выражений. Дополнительные сведения о квантификаторах см. в разделе Quantifiers.
  • Включите подвыражение в строку, возвращаемую методами Regex.Replace и Match.Result.
  • Извлекать отдельные подвыражения из свойства 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 '{match.Groups[1].Value}' found at positions {match.Groups[1].Index} and {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

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

Расписание Описание
(\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 '{match.Groups["duplicateWord"].Value}' at position {match.Groups["duplicateWord"].Index} is followed by '{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+)

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

Расписание Описание
(?<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: {m.Value}");
            for (int grpCtr = 1; grpCtr < m.Groups.Count; grpCtr++) {
               Group grp = m.Groups[grpCtr];
               Console.WriteLine($"Group {grpCtr}: {grp.Value}");
               for (int capCtr = 0; capCtr < grp.Captures.Count; capCtr++)
                  Console.WriteLine($"   Capture {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

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

Расписание Описание
\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: \"{input}\" \nMatch: \"{m}\"");
         int grpCtr = 0;
         foreach (Group grp in m.Groups)
         {
            Console.WriteLine($"   Group {grpCtr}: {grp.Value}");
            grpCtr++;
            int capCtr = 0;
            foreach (Capture cap in grp.Captures)
            {
                Console.WriteLine($"      Capture {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)(?!))$

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

Расписание Описание
^ Начало с первого символа строки.
[^<>]* Сопоставление нуля или большего числа символов, которые не являются правой или левой угловой скобкой.
(?'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>".
14 [^<>]* Соответствует "xyz".
15 )+ "<xyz" — это значение второй захваченной группы.

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

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

Следующий символ во входной строке не является правой угловой скобкой, поэтому механизм регулярных выражений не возвращается к подшаблону ((?'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: {match.Value}");
      for (int ctr = 1; ctr < match.Groups.Count; ctr++)
         Console.WriteLine($"   Group {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*)+\. сопоставляет предложение, которое завершается точкой. Поскольку регулярное выражение фокусируется на предложениях, а не на отдельных словах, конструкции группировки используются исключительно как квантификаторы. Возможные интерпретации шаблона регулярного выражения показаны в следующей таблице.

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

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

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

(?imnsx-imnsx: subexpression)

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

Примечание.

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

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

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

Расписание Описание
\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($"'{match.Value}// found at index {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($"'{match.Value}' precedes 'is'.");
         else
            Console.WriteLine($"'{input}' does not match the pattern.");
      }
   }
}
// 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) показаны в следующей таблице.

Расписание Описание
\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 показаны в следующей таблице.

Расписание Описание
\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}) показаны в следующей таблице.

Расписание Описание
\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 показаны в следующей таблице.

Расписание Описание
\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 показаны в следующей таблице.

Расписание Описание
\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($"{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 показано в следующей таблице.

Расписание Описание
(\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: '{match.Value}'");
      for (int ctr = 1; ctr < match.Groups.Count; ctr++)
      {
         Console.WriteLine($"   Group {ctr}: '{match.Groups[ctr].Value}'");
         int capCtr = 0;
         foreach (Capture capture in match.Groups[ctr].Captures)
         {
            Console.WriteLine($"      Capture {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+)+ извлекает отдельные слова из строки. Определяется, как показано в следующей таблице.

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

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

См. также