Различия между .NET Capture, Group, Match

Я делаю небольшое приложение с использованием типов .NET Regex. И типы "Capture, Group and Match" полностью смутили меня. Я никогда не видел такого уродливого решения. Может ли кто-нибудь объяснить их использование для меня? Большое спасибо.

Ответ 1

Здесь более простой пример, чем тот, который приведен в документе @Dav:

string s0 = @"foo%123%456%789";
Regex r0 = new Regex(@"^([a-z]+)(?:%([0-9]+))+$");
Match m0 = r0.Match(s0);
if (m0.Success)
{
  Console.WriteLine(@"full match: {0}", m0.Value);
  Console.WriteLine(@"group #1: {0}", m0.Groups[1].Value);
  Console.WriteLine(@"group #2: {0}", m0.Groups[2].Value);
  Console.WriteLine(@"group #2 captures: {0}, {1}, {2}",
                    m0.Groups[2].Captures[0].Value,
                    m0.Groups[2].Captures[1].Value,
                    m0.Groups[2].Captures[2].Value);
}

результат:

full match: foo%123%456%789
group #1: foo
group #2: 789
group #2 captures: 123, 456, 789

Результаты full match и group #1 просты, но другие требуют некоторого объяснения. Группа № 2, как вы можете видеть, находится внутри группы, не связанной с захватом, которая контролируется квантором +. Он соответствует три раза, но если вы запросите его Value, вы получите только то, что он сопоставил в третий раз - окончательный захват. Аналогичным образом, если вы используете заполнитель $2 в заменяющей строке, конечный захват - это то, что вставлено на его место.

В большинстве ароматов регулярных выражений это все, что вы можете получить; каждый промежуточный захват перезаписывается следующим и утерян;.NET почти уникален в сохранении всех захватов и делает их доступными после выполнения матча. Вы можете получить к ним доступ непосредственно, как я сделал здесь, или выполнить итерацию через CaptureCollection, как и MatchCollection. Однако нет эквивалента для заполнителей $1 -style replace-string.

Итак, причина, по которой дизайн API настолько уродлив (как вы выразились), двояка: сначала он был адаптирован из поддержки регулярного выражения Perl для объектно-ориентированной среды .NET; затем на него была привита структура CaptureCollection. Perl 6 предлагает гораздо более чистое решение, но авторы сделали это, переписывая Perl практически с нуля и отбрасывая обратную совместимость с окном.

Ответ 2

Соответствие - результат любого индивидуального соответствия всего регулярного выражения. Группы и захваты имеют как-то отношение к группам захвата (каждый (expression) из регулярного выражения), но различаются в том, как они себя ведут. Вот цитата из статьи MSDN в классе Capture, которая объясняет разницу:

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

(Источник)