Объектная модель регулярных выражений
В этой статье описывается объектная модель, используемая при работе с регулярными выражениями .NET.
Механизм регулярных выражений
Механизм регулярных выражений в .NET представлен классом Regex. Механизм отвечает за синтаксический анализ и компиляцию регулярного выражение, а также выполнение операций, которые сопоставляют шаблон регулярного выражения с входной строкой. Этот механизм представляет центральный компонент объектной модели регулярных выражений .NET.
Вы можете использовать механизм регулярных выражений одним из двух способов:
Вызывая статичные методы класса Regex. Параметры метода включают в себя входную строку и шаблон регулярного выражения. Механизм регулярных выражений кэширует регулярные выражения, которые используются в вызовах статичных методов, чтобы повторные вызовы статичных методов регулярных выражений, применяющие одно и то же регулярное выражение, выполнялись относительно быстро.
Создав Regex экземпляр объекта, то есть передав регулярное выражение конструктору класса. В этом случае объект Regex не изменяется (доступен только для чтения) и представляет механизм регулярных выражений, который тесно связана с одним регулярным выражением. Так как регулярные выражения, используемые Regex экземплярами, не кэшируются, не следует создавать экземпляр Regex объекта несколько раз с одинаковым регулярным выражением.
Вы можете вызывать методы класса Regex, чтобы выполнить следующие операции:
- определить, соответствует ли строка шаблону регулярного выражения;
- извлечь одно сопоставление или первое сопоставление;
- извлечь все сопоставления;
- заменить сопоставленную подстроку;
- разделить одну строку на массив строк.
Эти операции описаны в следующих разделах.
Сопоставление шаблона регулярного выражения
Метод Regex.IsMatch возвращает значение true
, если строка соответствует шаблону; в противном случае возвращается значение false
. Метод IsMatch часто используется для проверки входной строки. Например, следующий код проверяет, содержит ли строка допустимый номер социального страхования для США.
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string[] values = { "111-22-3333", "111-2-3333"};
string pattern = @"^\d{3}-\d{2}-\d{4}$";
foreach (string value in values) {
if (Regex.IsMatch(value, pattern))
Console.WriteLine("{0} is a valid SSN.", value);
else
Console.WriteLine("{0}: Invalid", value);
}
}
}
// The example displays the following output:
// 111-22-3333 is a valid SSN.
// 111-2-3333: Invalid
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim values() As String = {"111-22-3333", "111-2-3333"}
Dim pattern As String = "^\d{3}-\d{2}-\d{4}$"
For Each value As String In values
If Regex.IsMatch(value, pattern) Then
Console.WriteLine("{0} is a valid SSN.", value)
Else
Console.WriteLine("{0}: Invalid", value)
End If
Next
End Sub
End Module
' The example displays the following output:
' 111-22-3333 is a valid SSN.
' 111-2-3333: Invalid
Возможные интерпретации шаблона регулярного выражения ^\d{3}-\d{2}-\d{4}$
показаны в следующей таблице.
Расписание | Description |
---|---|
^ |
Выделение начала входной строки. |
\d{3} |
Совпадение с тремя десятичными цифрами. |
- |
Выделение дефиса. |
\d{2} |
Совпадение с двумя десятичными цифрами. |
- |
Выделение дефиса. |
\d{4} |
Выделяются 4 десятичные цифры. |
$ |
Соответствует концу входной строки. |
Извлечение одного совпадения или первого совпадения
Метод Regex.Match возвращает объект Match, который содержит сведения о первой подстроке, соответствующей шаблону регулярного выражения. Если свойство Match.Success
возвращает значение true
(найдено соответствие), вы можете получить информацию о последующих соответствиях, вызвав метод Match.NextMatch. Этот метод можно вызывать, пока свойство Match.Success
не вернет значение false
. Например, следующий код использует метод Regex.Match(String, String) для поиска первого экземпляра повторяющегося слова в строке. Затем вызывается метод Match.NextMatch для поиска других экземпляров. Пример просматривает свойство Match.Success
после каждого вызова метода, чтобы определить, было ли текущее сопоставление успешным и следует ли вызывать метод Match.NextMatch.
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string input = "This is a a farm that that raises dairy cattle.";
string pattern = @"\b(\w+)\W+(\1)\b";
Match match = Regex.Match(input, pattern);
while (match.Success)
{
Console.WriteLine("Duplicate '{0}' found at position {1}.",
match.Groups[1].Value, match.Groups[2].Index);
match = match.NextMatch();
}
}
}
// The example displays the following output:
// Duplicate 'a' found at position 10.
// Duplicate 'that' found at position 22.
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim input As String = "This is a a farm that that raises dairy cattle."
Dim pattern As String = "\b(\w+)\W+(\1)\b"
Dim match As Match = Regex.Match(input, pattern)
Do While match.Success
Console.WriteLine("Duplicate '{0}' found at position {1}.", _
match.Groups(1).Value, match.Groups(2).Index)
match = match.NextMatch()
Loop
End Sub
End Module
' The example displays the following output:
' Duplicate 'a' found at position 10.
' Duplicate 'that' found at position 22.
Возможные интерпретации шаблона регулярного выражения \b(\w+)\W+(\1)\b
показаны в следующей таблице.
Расписание | Description |
---|---|
\b |
Сопоставление начинается на границе слова. |
(\w+) |
Совпадение с одним или несколькими символами слова. Это первая группа записи. |
\W+ |
Совпадение с одним или большим числом несловообразующих символов. |
(\1) |
Выделение первой захватываемой строки. Это вторая группа записи. |
\b |
Сопоставление заканчивается на границе слова. |
Извлечение всех совпадений
Метод Regex.Matches возвращает объект MatchCollection, содержащий сведения о всех сопоставлениях, найденных механизмом регулярных выражений во входной строке. Например, предыдущий пример можно изменить, чтобы вызывать метод Matches вместо методов Match и NextMatch.
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string input = "This is a a farm that that raises dairy cattle.";
string pattern = @"\b(\w+)\W+(\1)\b";
foreach (Match match in Regex.Matches(input, pattern))
Console.WriteLine("Duplicate '{0}' found at position {1}.",
match.Groups[1].Value, match.Groups[2].Index);
}
}
// The example displays the following output:
// Duplicate 'a' found at position 10.
// Duplicate 'that' found at position 22.
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim input As String = "This is a a farm that that raises dairy cattle."
Dim pattern As String = "\b(\w+)\W+(\1)\b"
For Each match As Match In Regex.Matches(input, pattern)
Console.WriteLine("Duplicate '{0}' found at position {1}.", _
match.Groups(1).Value, match.Groups(2).Index)
Next
End Sub
End Module
' The example displays the following output:
' Duplicate 'a' found at position 10.
' Duplicate 'that' found at position 22.
Замена сопоставленной подстроки
Метод Regex.Replace заменяет каждую подстроку, соответствующую шаблону регулярного выражения, на указанную строку или шаблон регулярного выражения и возвращает всю замененную входную строку. Например, следующий код добавляет обозначение денежной единицы США перед десятичным числом в строке.
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = @"\b\d+\.\d{2}\b";
string replacement = "$$$&";
string input = "Total Cost: 103.64";
Console.WriteLine(Regex.Replace(input, pattern, replacement));
}
}
// The example displays the following output:
// Total Cost: $103.64
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim pattern As String = "\b\d+\.\d{2}\b"
Dim replacement As String = "$$$&"
Dim input As String = "Total Cost: 103.64"
Console.WriteLine(Regex.Replace(input, pattern, replacement))
End Sub
End Module
' The example displays the following output:
' Total Cost: $103.64
Возможные интерпретации шаблона регулярного выражения \b\d+\.\d{2}\b
показаны в следующей таблице.
Расписание | Description |
---|---|
\b |
Совпадение должно начинаться на границе слова. |
\d+ |
Совпадение с одной или несколькими десятичными цифрами. |
\. |
Сопоставляется точка. |
\d{2} |
Совпадение с двумя десятичными цифрами. |
\b |
Совпадение должно заканчиваться на границе слова. |
Шаблон замены $$$&
интерпретируется, как показано в следующей таблице.
Расписание | Строка замены |
---|---|
$$ |
Символ доллара ($). |
$& |
Вся сопоставленная подстрока. |
Разделение одной строки на массив строк
Метод Regex.Split разделяет входную строку в позициях, заданных соответствием регулярного выражения. Например, следующий код помещает элементы нумерованного списка в массив строк.
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string input = "1. Eggs 2. Bread 3. Milk 4. Coffee 5. Tea";
string pattern = @"\b\d{1,2}\.\s";
foreach (string item in Regex.Split(input, pattern))
{
if (! String.IsNullOrEmpty(item))
Console.WriteLine(item);
}
}
}
// The example displays the following output:
// Eggs
// Bread
// Milk
// Coffee
// Tea
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim input As String = "1. Eggs 2. Bread 3. Milk 4. Coffee 5. Tea"
Dim pattern As String = "\b\d{1,2}\.\s"
For Each item As String In Regex.Split(input, pattern)
If Not String.IsNullOrEmpty(item) Then
Console.WriteLine(item)
End If
Next
End Sub
End Module
' The example displays the following output:
' Eggs
' Bread
' Milk
' Coffee
' Tea
Возможные интерпретации шаблона регулярного выражения \b\d{1,2}\.\s
показаны в следующей таблице.
Расписание | Description |
---|---|
\b |
Совпадение должно начинаться на границе слова. |
\d{1,2} |
Совпадение с одной или двумя десятичными цифрами. |
\. |
Сопоставляется точка. |
\s |
Соответствует пробелу. |
Объекты MatchCollection
и Match
объекты
Методы Regex возвращают два объекта, входящие в объектную модель регулярного выражения: MatchCollection и Match.
Класс MatchCollection
Метод Regex.Matches возвращает объект MatchCollection, содержащий объекты Match, которые представляют все сопоставления, найденных механизмом регулярных выражений, в том порядке, в котором они присутствуют во входной строке. Если соответствий нет, метод возвращает объект MatchCollection без членов. Свойство MatchCollection.Item[] позволяет получить доступ к отдельным членам коллекции по индексу (от нуля до значения свойства MatchCollection.Count минус 1). Item[] — это индексатор коллекции (для C#) и свойство по умолчанию (для Visual Basic).
По умолчанию вызов метода Regex.Matches использует отложенные вычисления для заполнения объекта MatchCollection. Доступ к свойствам, которым требуется полностью заполненная коллекция, например свойства MatchCollection.Count и MatchCollection.Item[], может быть связан с дополнительными затратами. Поэтому мы рекомендуем обращаться к коллекции, используя объект IEnumerator, возвращаемый методом MatchCollection.GetEnumerator. Некоторые языки предоставляют конструкции, такие как For Each
в Visual Basic и foreach
в C#, которые создают оболочку для интерфейса IEnumerator коллекции.
Следующий пример использует метод Regex.Matches(String) для заполнения объекта MatchCollection всеми соответствиями, найденными во входной строке. Пример перечисляет коллекцию, копирует соответствия в массив строк и записывает позиции символов в целочисленный массив.
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
MatchCollection matches;
List<string> results = new List<string>();
List<int> matchposition = new List<int>();
// Create a new Regex object and define the regular expression.
Regex r = new Regex("abc");
// Use the Matches method to find all matches in the input string.
matches = r.Matches("123abc4abcd");
// Enumerate the collection to retrieve all matches and positions.
foreach (Match match in matches)
{
// Add the match string to the string array.
results.Add(match.Value);
// Record the character position where the match was found.
matchposition.Add(match.Index);
}
// List the results.
for (int ctr = 0; ctr < results.Count; ctr++)
Console.WriteLine("'{0}' found at position {1}.",
results[ctr], matchposition[ctr]);
}
}
// The example displays the following output:
// 'abc' found at position 3.
// 'abc' found at position 7.
Imports System.Collections.Generic
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim matches As MatchCollection
Dim results As New List(Of String)
Dim matchposition As New List(Of Integer)
' Create a new Regex object and define the regular expression.
Dim r As New Regex("abc")
' Use the Matches method to find all matches in the input string.
matches = r.Matches("123abc4abcd")
' Enumerate the collection to retrieve all matches and positions.
For Each match As Match In matches
' Add the match string to the string array.
results.Add(match.Value)
' Record the character position where the match was found.
matchposition.Add(match.Index)
Next
' List the results.
For ctr As Integer = 0 To results.Count - 1
Console.WriteLine("'{0}' found at position {1}.", _
results(ctr), matchposition(ctr))
Next
End Sub
End Module
' The example displays the following output:
' 'abc' found at position 3.
' 'abc' found at position 7.
Класс Match
Класс Match представляет результат одного сопоставления регулярного выражения. Доступ к объектам Match можно получить двумя способами:
Извлекая их из объекта MatchCollection, который возвращается методом Regex.Matches. Для извлечения отдельных объектов Match выполните итерацию коллекции, воспользовавшись конструкцией
foreach
(в C#) илиFor Each
...Next
(в Visual Basic), либо используйте свойство MatchCollection.Item[] для извлечения конкретного объекта Match по индексу или по имени. Вы также можете получить отдельные объекты Match из коллекции, циклически проходя по коллекции по индексу (от нуля до числа объектов в коллекции минус 1). Однако этот метод не использует отложенные вычисления, так как он обращается к свойству MatchCollection.Count.Следующий пример извлекает отдельные объекты Match из объекта MatchCollection, циклически перебирая коллекцию с помощью конструкции
foreach
илиFor Each
...Next
. Регулярное выражение просто сопоставляет строку "abc" во входной строке.using System; using System.Text.RegularExpressions; public class Example { public static void Main() { string pattern = "abc"; string input = "abc123abc456abc789"; foreach (Match match in Regex.Matches(input, pattern)) Console.WriteLine("{0} found at position {1}.", match.Value, match.Index); } } // The example displays the following output: // abc found at position 0. // abc found at position 6. // abc found at position 12.
Imports System.Text.RegularExpressions Module Example Public Sub Main() Dim pattern As String = "abc" Dim input As String = "abc123abc456abc789" For Each match As Match In Regex.Matches(input, pattern) Console.WriteLine("{0} found at position {1}.", _ match.Value, match.Index) Next End Sub End Module ' The example displays the following output: ' abc found at position 0. ' abc found at position 6. ' abc found at position 12.
Вызывая метод Regex.Match, который возвращает объект Match, представляющий первое соответствие в строке или ее части. Вы можете определить, найдено ли соответствие, получив значение свойства
Match.Success
. Чтобы извлечь объекты Match, представляющие последующие соответствия, вызывайте метод Match.NextMatch, пока свойствоSuccess
полученного объекта Match не будет иметь значениеfalse
.Следующий пример использует методы Regex.Match(String, String) и Match.NextMatch для сопоставления строки "abc" во входной строке.
using System; using System.Text.RegularExpressions; public class Example { public static void Main() { string pattern = "abc"; string input = "abc123abc456abc789"; Match match = Regex.Match(input, pattern); while (match.Success) { Console.WriteLine("{0} found at position {1}.", match.Value, match.Index); match = match.NextMatch(); } } } // The example displays the following output: // abc found at position 0. // abc found at position 6. // abc found at position 12.
Imports System.Text.RegularExpressions Module Example Public Sub Main() Dim pattern As String = "abc" Dim input As String = "abc123abc456abc789" Dim match As Match = Regex.Match(input, pattern) Do While match.Success Console.WriteLine("{0} found at position {1}.", _ match.Value, match.Index) match = match.NextMatch() Loop End Sub End Module ' The example displays the following output: ' abc found at position 0. ' abc found at position 6. ' abc found at position 12.
Два свойства класса Match возвращают объекты коллекции:
Свойство Match.Groups возвращает объект GroupCollection, который содержит сведения о подстроках, соответствующих захватываемым группам в шаблоне регулярного выражения.
Свойство
Match.Captures
возвращает объект CaptureCollection с ограниченным применением. Коллекция не заполняется для объекта Match, свойствоSuccess
которого имеет значениеfalse
. В противном случае она содержит один объект Capture, содержащий такие же данные, что и объект Match.
Дополнительные сведения об этих объектах см. в разделах GroupCollection
"Класс" и "Разделы CaptureCollection
классов" далее в этой статье.
Два дополнительных свойства класса Match предоставляют сведения о соответствии. Свойство Match.Value
возвращает подстроку из входной строки, соответствующую шаблону регулярного выражения. Свойства Match.Index
возвращает начальную позицию сопоставленной подстроки во входной строке с основанием ноль.
Класс Match также содержит два метода сопоставления шаблона:
Метод Match.NextMatch ищет совпадение после соответствия, представленного текущим объектом Match, и возвращает объект Match, представляющий соответствие.
Метод Match.Result выполняет указанную замену в сопоставленной строке и возвращает результат.
В следующем примере метод Match.Result используется для добавления символа $ и пробела перед каждым числом из двух дробных разрядов.
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = @"\b\d+(,\d{3})*\.\d{2}\b";
string input = "16.32\n194.03\n1,903,672.08";
foreach (Match match in Regex.Matches(input, pattern))
Console.WriteLine(match.Result("$$ $&"));
}
}
// The example displays the following output:
// $ 16.32
// $ 194.03
// $ 1,903,672.08
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim pattern As String = "\b\d+(,\d{3})*\.\d{2}\b"
Dim input As String = "16.32" + vbCrLf + "194.03" + vbCrLf + "1,903,672.08"
For Each match As Match In Regex.Matches(input, pattern)
Console.WriteLine(match.Result("$$ $&"))
Next
End Sub
End Module
' The example displays the following output:
' $ 16.32
' $ 194.03
' $ 1,903,672.08
Шаблон регулярного выражения \b\d+(,\d{3})*\.\d{2}\b
определяется, как показано в следующей таблице.
Расписание | Description |
---|---|
\b |
Совпадение должно начинаться на границе слова. |
\d+ |
Совпадение с одной или несколькими десятичными цифрами. |
(,\d{3})* |
Совпадение с нулем или несколькими вхождениями запятой, за которыми следуют три десятичные цифры. |
\. |
Совпадение с символом десятичной точки. |
\d{2} |
Совпадение с двумя десятичными цифрами. |
\b |
Совпадение должно заканчиваться на границе слова. |
Шаблон замены $$ $&
указывает, что сопоставленную подстроку следует заменить на символ доллара ($) (шаблон $$
), пробел и значение соответствия (шаблон $&
).
Класс GroupCollection
Свойство Match.Groups возвращает объект GroupCollection, содержащий объекты Group, которые представляют захватываемые группы в одном соответствии. Первый объект Group в коллекции (объект с нулевым индексом) представляет все сопоставление. Каждый последующий объект представляет результаты одной захватываемой группы.
Вы можете извлечь отдельные объекты Group из коллекции, используя свойство GroupCollection.Item[]. Неименованные группы можно извлечь по их номеру в коллекции, а именованные группы — по имени или номеру. Неименованные выделения идут в коллекции первыми и индексируются слева направо в том порядке, в котором они указаны в шаблоне регулярного выражения. Именованные выделения индексируются после неименованных слева направо в том порядке, в котором они указаны в шаблоне регулярного выражения. Чтобы определить, какие нумерованные группы доступны в коллекции, возвращаемой для определенного метода сопоставления регулярного выражения, вызовите метод Regex.GetGroupNumbers экземпляра. Чтобы определить, какие именованные группы доступны в коллекции, вызовите метод Regex.GetGroupNames экземпляра. Оба метода полезны в процедурах общего назначения, которые анализируют соответствия, найденные любым регулярным выражением.
Свойство GroupCollection.Item[] — это индексатор коллекции для C# и свойство объекта по умолчанию для Visual Basic. Это значит, что доступ к отдельным объектам Group можно получить по индексу (или, для именованных групп, по имени) следующим образом:
Group group = match.Groups[ctr];
Dim group As Group = match.Groups(ctr)
В следующем примере определяется регулярное выражение, которое использует конструкции группировки для выделения месяца, дня и года из даты.
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = @"\b(\w+)\s(\d{1,2}),\s(\d{4})\b";
string input = "Born: July 28, 1989";
Match match = Regex.Match(input, pattern);
if (match.Success)
for (int ctr = 0; ctr < match.Groups.Count; ctr++)
Console.WriteLine("Group {0}: {1}", ctr, match.Groups[ctr].Value);
}
}
// The example displays the following output:
// Group 0: July 28, 1989
// Group 1: July
// Group 2: 28
// Group 3: 1989
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim pattern As String = "\b(\w+)\s(\d{1,2}),\s(\d{4})\b"
Dim input As String = "Born: July 28, 1989"
Dim match As Match = Regex.Match(input, pattern)
If match.Success Then
For ctr As Integer = 0 To match.Groups.Count - 1
Console.WriteLine("Group {0}: {1}", ctr, match.Groups(ctr).Value)
Next
End If
End Sub
End Module
' The example displays the following output:
' Group 0: July 28, 1989
' Group 1: July
' Group 2: 28
' Group 3: 1989
Шаблон регулярного выражения \b(\w+)\s(\d{1,2}),\s(\d{4})\b
определяется, как показано в следующей таблице.
Расписание | Description |
---|---|
\b |
Совпадение должно начинаться на границе слова. |
(\w+) |
Совпадение с одним или несколькими символами слова. Это первая группа записи. |
\s |
Соответствует пробелу. |
(\d{1,2}) |
Совпадение с одной или двумя десятичными цифрами. Это вторая группа записи. |
, |
Сопоставление запятой. |
\s |
Соответствует пробелу. |
(\d{4}) |
Выделяются 4 десятичные цифры. Это третья группа записи. |
\b |
Сопоставление заканчивается на границе слова. |
Захватываемая группа
Класс Group представляет результат одной захватываемой группы. Объекты Group, представляющие захватываемые группы, заданные в регулярном выражении, возвращаются свойством Item[] объекта GroupCollection, который возвращается свойством Match.Groups. Свойство Item[] — это индексатор (для C#) и свойство по умолчанию (для Visual Basic) класса Group. Вы также можете извлечь отдельные члены, циклически перебирая коллекцию с помощью конструкции foreach
или For Each
. Пример см. в предыдущем разделе.
В следующем примере вложенные конструкции группировки используются для записи подстрок в группы. Шаблон регулярного выражения (a(b))c
сопоставляет строку "abc". Он назначает подстроку "ab" первой захватываемой группе, а подстроку "b" — второй захватываемой группе.
var matchposition = new List<int>();
var results = new List<string>();
// Define substrings abc, ab, b.
var r = new Regex("(a(b))c");
Match m = r.Match("abdabc");
for (int i = 0; m.Groups[i].Value != ""; i++)
{
// Add groups to string array.
results.Add(m.Groups[i].Value);
// Record character position.
matchposition.Add(m.Groups[i].Index);
}
// Display the capture groups.
for (int ctr = 0; ctr < results.Count; ctr++)
Console.WriteLine("{0} at position {1}",
results[ctr], matchposition[ctr]);
// The example displays the following output:
// abc at position 3
// ab at position 3
// b at position 4
Dim matchposition As New List(Of Integer)
Dim results As New List(Of String)
' Define substrings abc, ab, b.
Dim r As New Regex("(a(b))c")
Dim m As Match = r.Match("abdabc")
Dim i As Integer = 0
While Not (m.Groups(i).Value = "")
' Add groups to string array.
results.Add(m.Groups(i).Value)
' Record character position.
matchposition.Add(m.Groups(i).Index)
i += 1
End While
' Display the capture groups.
For ctr As Integer = 0 to results.Count - 1
Console.WriteLine("{0} at position {1}", _
results(ctr), matchposition(ctr))
Next
' The example displays the following output:
' abc at position 3
' ab at position 3
' b at position 4
В следующем примере именованные конструкции группировки используются для выделения подстрок из строки, содержащей данные в формате "DATANAME:VALUE", которые регулярное выражение разделяет в позиции двоеточия (:).
var r = new Regex(@"^(?<name>\w+):(?<value>\w+)");
Match m = r.Match("Section1:119900");
Console.WriteLine(m.Groups["name"].Value);
Console.WriteLine(m.Groups["value"].Value);
// The example displays the following output:
// Section1
// 119900
Dim r As New Regex("^(?<name>\w+):(?<value>\w+)")
Dim m As Match = r.Match("Section1:119900")
Console.WriteLine(m.Groups("name").Value)
Console.WriteLine(m.Groups("value").Value)
' The example displays the following output:
' Section1
' 119900
Шаблон регулярного выражения ^(?<name>\w+):(?<value>\w+)
определяется, как показано в следующей таблице.
Расписание | Description |
---|---|
^ |
Начало совпадения в начале входной строки. |
(?<name>\w+) |
Совпадение с одним или несколькими символами слова. Имя захватываемой группы — name . |
: |
Сопоставление двоеточия. |
(?<value>\w+) |
Совпадение с одним или несколькими символами слова. Имя захватываемой группы — value . |
Свойства класса Group предоставляют сведения о захватываемой группе: свойство Group.Value
содержит выделенную подстроку, свойство Group.Index
указывает начальную позицию захватываемой группы во входном тексте, свойство Group.Length
содержит длину выделенного текста, а свойство Group.Success
указывает, соответствует ли подстрока шаблону, заданному захватываемой группой.
Применение квантификаторов к группе (см. раздел Квантификаторы) изменяет связь одного выделения в захватываемой группе двумя способами:
Если квантификатор
*
или*?
(который указывает ноль или больше соответствий) применен к группе, во входной строке может отсутствовать соответствие захватываемой группе. Если выделенного текста нет, свойства объекта Group задаются, как показано в следующей таблице.Свойство объекта Group Значение Success
false
Value
String.Empty Length
0 Это показывается в следующем примере. В шаблоне регулярного выражения
aaa(bbb)*ccc
первая захватываемая группа (подстрока "bbb") может быть сопоставлена ноль или больше раз. Так как входная строка "aaaccc" соответствует шаблону, захватываемая группа не имеет соответствия.using System; using System.Text.RegularExpressions; public class Example { public static void Main() { string pattern = "aaa(bbb)*ccc"; string input = "aaaccc"; Match match = Regex.Match(input, pattern); Console.WriteLine("Match value: {0}", match.Value); if (match.Groups[1].Success) Console.WriteLine("Group 1 value: {0}", match.Groups[1].Value); else Console.WriteLine("The first capturing group has no match."); } } // The example displays the following output: // Match value: aaaccc // The first capturing group has no match.
Imports System.Text.RegularExpressions Module Example Public Sub Main() Dim pattern As String = "aaa(bbb)*ccc" Dim input As String = "aaaccc" Dim match As Match = Regex.Match(input, pattern) Console.WriteLine("Match value: {0}", match.Value) If match.Groups(1).Success Then Console.WriteLine("Group 1 value: {0}", match.Groups(1).Value) Else Console.WriteLine("The first capturing group has no match.") End If End Sub End Module ' The example displays the following output: ' Match value: aaaccc ' The first capturing group has no match.
Квантификаторы могут сопоставлять множество вхождений шаблона, заданного захватываемой группой. В этом случае свойства
Value
иLength
объекта Group содержат сведения только о последней выделенной подстроке. Например, следующее регулярное выражение сопоставляет предложение, заканчивающееся на точку. Оно использует две конструкции группировки: первая выделяет отдельные слова вместе с пробелом, вторая выделяет отдельные слова. Как видно из результата выполнения примера, хотя регулярное выражение успешно выделяет все предложение, вторая захватываемая группа выделяет только последнее слово.using System; using System.Text.RegularExpressions; public class Example { public static void Main() { string pattern = @"\b((\w+)\s?)+\."; string input = "This is a sentence. This is another sentence."; Match match = Regex.Match(input, pattern); if (match.Success) { Console.WriteLine("Match: " + match.Value); Console.WriteLine("Group 2: " + match.Groups[2].Value); } } } // The example displays the following output: // Match: This is a sentence. // Group 2: sentence
Imports System.Text.RegularExpressions Module Example Public Sub Main() Dim pattern As String = "\b((\w+)\s?)+\." Dim input As String = "This is a sentence. This is another sentence." Dim match As Match = Regex.Match(input, pattern) If match.Success Then Console.WriteLine("Match: " + match.Value) Console.WriteLine("Group 2: " + match.Groups(2).Value) End If End Sub End Module ' The example displays the following output: ' Match: This is a sentence. ' Group 2: sentence
Класс CaptureCollection
Объект Group содержит сведения только о последнем выделении. Однако весь набор выделений, созданный захватываемой группой, по-прежнему доступен из объекта CaptureCollection, возвращаемого свойством Group.Captures. Каждый член коллекции — это объект Capture, представляющий выделение этой захватываемой группы в порядке захвата (и, следовательно, в порядке сопоставления выделенных строк слева направо во входной строке). Вы можете извлечь отдельные объекты Capture из коллекции одним из двух способов:
циклически перебирая коллекцию с помощью конструкции
foreach
(для C#) илиFor Each
(для Visual Basic);используя свойство CaptureCollection.Item[] для извлечения определенного объекта по индексу. Свойство Item[] — это свойство по умолчанию (для Visual Basic) индексатор (для C#) класса CaptureCollection.
Если квантификатор не применен к захватываемой группе, объект CaptureCollection содержит один объект Capture, который не представляет особого интереса, так как он содержит сведения о том же соответствии, что и объект Group. Если к захватываемой группе применен квантификатор, объект CaptureCollection содержит все выделения захватываемой группы, а последний член коллекции представляет то же выделение, что и объект Group.
Например, если использовать шаблон регулярного выражения ((a(b))c)+
(где квантификатор "+" указывает одно или несколько соответствий) для выделения соответствий из строки "abcabcabc", объект CaptureCollection для каждого объекта Group содержит три члена.
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = "((a(b))c)+";
string input = "abcabcabc";
Match match = Regex.Match(input, pattern);
if (match.Success)
{
Console.WriteLine("Match: '{0}' at position {1}",
match.Value, match.Index);
GroupCollection groups = match.Groups;
for (int ctr = 0; ctr < groups.Count; ctr++) {
Console.WriteLine(" Group {0}: '{1}' at position {2}",
ctr, groups[ctr].Value, groups[ctr].Index);
CaptureCollection captures = groups[ctr].Captures;
for (int ctr2 = 0; ctr2 < captures.Count; ctr2++) {
Console.WriteLine(" Capture {0}: '{1}' at position {2}",
ctr2, captures[ctr2].Value, captures[ctr2].Index);
}
}
}
}
}
// The example displays the following output:
// Match: 'abcabcabc' at position 0
// Group 0: 'abcabcabc' at position 0
// Capture 0: 'abcabcabc' at position 0
// Group 1: 'abc' at position 6
// Capture 0: 'abc' at position 0
// Capture 1: 'abc' at position 3
// Capture 2: 'abc' at position 6
// Group 2: 'ab' at position 6
// Capture 0: 'ab' at position 0
// Capture 1: 'ab' at position 3
// Capture 2: 'ab' at position 6
// Group 3: 'b' at position 7
// Capture 0: 'b' at position 1
// Capture 1: 'b' at position 4
// Capture 2: 'b' at position 7
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim pattern As String = "((a(b))c)+"
Dim input As STring = "abcabcabc"
Dim match As Match = Regex.Match(input, pattern)
If match.Success Then
Console.WriteLine("Match: '{0}' at position {1}", _
match.Value, match.Index)
Dim groups As GroupCollection = match.Groups
For ctr As Integer = 0 To groups.Count - 1
Console.WriteLine(" Group {0}: '{1}' at position {2}", _
ctr, groups(ctr).Value, groups(ctr).Index)
Dim captures As CaptureCollection = groups(ctr).Captures
For ctr2 As Integer = 0 To captures.Count - 1
Console.WriteLine(" Capture {0}: '{1}' at position {2}", _
ctr2, captures(ctr2).Value, captures(ctr2).Index)
Next
Next
End If
End Sub
End Module
' The example displays the following output:
' Match: 'abcabcabc' at position 0
' Group 0: 'abcabcabc' at position 0
' Capture 0: 'abcabcabc' at position 0
' Group 1: 'abc' at position 6
' Capture 0: 'abc' at position 0
' Capture 1: 'abc' at position 3
' Capture 2: 'abc' at position 6
' Group 2: 'ab' at position 6
' Capture 0: 'ab' at position 0
' Capture 1: 'ab' at position 3
' Capture 2: 'ab' at position 6
' Group 3: 'b' at position 7
' Capture 0: 'b' at position 1
' Capture 1: 'b' at position 4
' Capture 2: 'b' at position 7
Следующий пример использует регулярное выражение (Abc)+
для поиска одного или нескольких последовательных вхождений строки "Abc" в строке "XYZAbcAbcAbcXYZAbcAb". Этот пример демонстрирует использование свойства Group.Captures для получения нескольких групп выделенных подстрок.
int counter;
Match m;
CaptureCollection cc;
GroupCollection gc;
// Look for groupings of "Abc".
var r = new Regex("(Abc)+");
// Define the string to search.
m = r.Match("XYZAbcAbcAbcXYZAbcAb");
gc = m.Groups;
// Display the number of groups.
Console.WriteLine("Captured groups = " + gc.Count.ToString());
// Loop through each group.
for (int i = 0; i < gc.Count; i++)
{
cc = gc[i].Captures;
counter = cc.Count;
// Display the number of captures in this group.
Console.WriteLine("Captures count = " + counter.ToString());
// Loop through each capture in the group.
for (int ii = 0; ii < counter; ii++)
{
// Display the capture and its position.
Console.WriteLine(cc[ii] + " Starts at character " +
cc[ii].Index);
}
}
// The example displays the following output:
// Captured groups = 2
// Captures count = 1
// AbcAbcAbc Starts at character 3
// Captures count = 3
// Abc Starts at character 3
// Abc Starts at character 6
// Abc Starts at character 9
Dim counter As Integer
Dim m As Match
Dim cc As CaptureCollection
Dim gc As GroupCollection
' Look for groupings of "Abc".
Dim r As New Regex("(Abc)+")
' Define the string to search.
m = r.Match("XYZAbcAbcAbcXYZAbcAb")
gc = m.Groups
' Display the number of groups.
Console.WriteLine("Captured groups = " & gc.Count.ToString())
' Loop through each group.
Dim i, ii As Integer
For i = 0 To gc.Count - 1
cc = gc(i).Captures
counter = cc.Count
' Display the number of captures in this group.
Console.WriteLine("Captures count = " & counter.ToString())
' Loop through each capture in the group.
For ii = 0 To counter - 1
' Display the capture and its position.
Console.WriteLine(cc(ii).ToString() _
& " Starts at character " & cc(ii).Index.ToString())
Next ii
Next i
' The example displays the following output:
' Captured groups = 2
' Captures count = 1
' AbcAbcAbc Starts at character 3
' Captures count = 3
' Abc Starts at character 3
' Abc Starts at character 6
' Abc Starts at character 9
Класс Capture
Класс Capture содержит результаты одного выделения части выражения. Свойство Capture.Value содержит сопоставленный текст, а свойство Capture.Index указывает начальную позицию сопоставленной подстроки во входной строке с основанием ноль.
Следующий пример ищет во входной строке температуру выбранных городов. Запятая (",") используется для разделения города и температуры, а точка с запятой (";") — для разделения данных каждого города. Вся входная строка представляет одно соответствие. В шаблоне регулярного выражения ((\w+(\s\w+)*),(\d+);)+
, который используется для анализа строки, название города назначается второй захватываемой группе, а температура — четвертой захватываемой группе.
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string input = "Miami,78;Chicago,62;New York,67;San Francisco,59;Seattle,58;";
string pattern = @"((\w+(\s\w+)*),(\d+);)+";
Match match = Regex.Match(input, pattern);
if (match.Success)
{
Console.WriteLine("Current temperatures:");
for (int ctr = 0; ctr < match.Groups[2].Captures.Count; ctr++)
Console.WriteLine("{0,-20} {1,3}", match.Groups[2].Captures[ctr].Value,
match.Groups[4].Captures[ctr].Value);
}
}
}
// The example displays the following output:
// Current temperatures:
// Miami 78
// Chicago 62
// New York 67
// San Francisco 59
// Seattle 58
Imports System.Text.RegularExpressions
Module Example
Public Sub Main()
Dim input As String = "Miami,78;Chicago,62;New York,67;San Francisco,59;Seattle,58;"
Dim pattern As String = "((\w+(\s\w+)*),(\d+);)+"
Dim match As Match = Regex.Match(input, pattern)
If match.Success Then
Console.WriteLine("Current temperatures:")
For ctr As Integer = 0 To match.Groups(2).Captures.Count - 1
Console.WriteLine("{0,-20} {1,3}", match.Groups(2).Captures(ctr).Value, _
match.Groups(4).Captures(ctr).Value)
Next
End If
End Sub
End Module
' The example displays the following output:
' Current temperatures:
' Miami 78
' Chicago 62
' New York 67
' San Francisco 59
' Seattle 58
Определение регулярного выражения показано в следующей таблице.
Расписание | Description |
---|---|
\w+ |
Совпадение с одним или несколькими символами слова. |
(\s\w+)* |
Сопоставляется ноль или несколько экземпляров пробела, за которыми следует один или несколько словообразующих символов. Этот шаблон выделяет названия городов из нескольких слов. Это третья группа записи. |
(\w+(\s\w+)*) |
Сопоставляется один или несколько словообразующих символов, за которыми следует ноль или несколько пробелов и один или несколько словообразующих символов. Это вторая группа записи. |
, |
Сопоставление запятой. |
(\d+) |
Сопоставление с одной или несколькими цифрами. Это четвертая группа записи. |
; |
Сопоставление точки с запятой. |
((\w+(\s\w+)*),(\d+);)+ |
Шаблона из слова, за которым следуют другие слова, запятая, одна или несколько цифр и точка запятая сопоставляется один или более раз. Это первая группа записи. |