Ты не будешь первым, кто не уверен в этом. Вот что говорит об этом знаменитый Джеффри Фридл (стр. 437+):
В зависимости от вашего взгляда, это либо добавляет интересное новое измерение к результатам матча, либо добавляет путаницу и раздувание.
И далее:
Основное различие между объектом Group и объектом Capture заключается в том, что каждый объект Group содержит коллекцию Captures, представляющую все промежуточные совпадения группы во время сопоставления, а также окончательный текст, сопоставленный группой.
И несколько страниц спустя, это его вывод:
После ознакомления с документацией .NET и понимания того, что добавляют эти объекты, у меня к ним смешанные чувства. С одной стороны, это интересное нововведение [...], с другой стороны, оно, кажется, добавляет бремя эффективности [..] функциональности, которая не будет использоваться в большинстве случаев
Другими словами: они очень похожи, но иногда и когда это происходит, вы найдете для них применение. Прежде чем отрастить еще одну седую бороду, вы можете даже полюбить пленники ...
Поскольку ни вышеперечисленное, ни то, что сказано в другом посте, похоже, на самом деле не отвечают на ваш вопрос, рассмотрите следующее. Думайте о Захватах как об историческом трекере. Когда регулярное выражение делает свое совпадение, оно проходит строку слева направо (на мгновение игнорируя обратное отслеживание), и когда оно встречает совпадающие захватывающие скобки, оно будет сохранять это в $x
(например, x - любая цифра) $1
.
Обычные движки регулярных выражений, когда необходимо повторить ввод скобок, отбрасывают ток $1
и заменяют его новым значением. Не .NET, которая будет хранить эту историю и помещать ее в Captures[0]
.
Если мы изменим ваше регулярное выражение, чтобы выглядеть следующим образом:
MatchCollection matches = Regex.Matches("{Q}{R}{S}", @"(\{[A-Z]\})+");
вы заметите, что у первой Group
будет одна Captures
(первая группа всегда будет соответствовать целику, т. е. равна $0
), а вторая группа будет содержать {S}
, то есть только последнюю группу соответствия. Тем не менее, и здесь есть загвоздка, если вы хотите найти две другие уловки, в которых они находятся Captures
, которая содержит все промежуточные записи для {Q}
{R}
и {S}
.
Если вы когда-нибудь задавались вопросом, как вы можете получить от множественного захвата, который показывает только последнее совпадение с отдельными снимками, которые явно присутствуют в строке, вы должны использовать Captures
.
Последнее слово в вашем последнем вопросе: общее совпадение всегда имеет один общий захват, не смешивайте это с отдельными группами. Захваты интересны только внутри групп .
a functionality that won't be used in the majority of cases
Я думаю, что он пропустил лодку. В краткосрочной перспективе(?:.*?(collection info)){4,20}
эффективность увеличивается более чем на несколько сотен процентов.(?:..)+
. Ленивое сопоставление чего-либо.*?
до подвыражения захвата (группы). Продолжайте дальше. В пределах одного совпадения групповая коллекция выделяет массив только того, что нужно. Нет необходимости искать дальше, нет повторного входа, что делает его в 10-20 и более раз быстрее.a functionality that won't be used in the majority of cases
. На самом деле это самая востребованная функциональность в регулярных выражениях. Ленивый / жадный? Какое это имеет отношение к моим комментариям? Это позволяет иметь переменное количество буферов захвата. Он может подмести всю строку в одном матче. Если.*?(dog)
находит первое,dog
то(?:.*?(dog))+
найдет всеdog
во всей строке в одном совпадении. Увеличение производительности заметно.Группа - это то, что мы связали с группами в регулярных выражениях
за исключением того, что это только «захваченные» группы. Группы без захвата (с использованием синтаксиса '(?:') Здесь не представлены.
Захват - также то, что мы связали с «захваченными группами». Но когда группа применяется с квантификатором несколько раз, только последнее совпадение сохраняется в качестве совпадения группы. Массив captures хранит все эти совпадения.
Что касается вашего последнего вопроса - я бы подумал, прежде чем рассматривать это, что Captures будет массивом захватов, упорядоченных группой, к которой они принадлежат. Скорее, это просто псевдоним групп [0] .Captures. Довольно бесполезно ..
источник
Это можно объяснить на простом примере (и рисунках).
Соответствие
3:10pm
с регулярным выражением((\d)+):((\d)+)(am|pm)
и использование Mono интерактивноcsharp
:Так где же 1?
Поскольку в четвертой группе есть несколько цифр, которые совпадают, мы только «получим» последнее совпадение, если будем ссылаться на группу (то есть неявно
ToString()
). Чтобы раскрыть промежуточные совпадения, нам нужно пойти глубже и ссылаться наCaptures
свойство в рассматриваемой группе:Предоставлено этой статьей .
источник
Из документации MSDN :
источник
Представьте, что у вас есть следующий текст
dogcatcatcat
и шаблонdog(cat(catcat))
В этом случае у вас есть 3 группы, первая ( основная группа ) соответствует матчу.
Match ==
dogcatcatcat
и Group0 ==dogcatcatcat
Group1 ==
catcatcat
Group2 ==
catcat
Так что же это такое?
Давайте рассмотрим небольшой пример, написанный на C # (.NET) с использованием
Regex
класса.Выход :
Давайте проанализируем только первое совпадение (
match0
).Как вы можете видеть , что есть три небольшие группы :
group3
,group4
иgroup5
Эти группы (3-5) были созданы из-за « подмаски »
(...)(...)(...)
из основного шаблона(dog(cat(...)(...)(...)))
Значение
group3
соответствует его захвату (capture0
). (Как и в случаеgroup4
иgroup5
). Это потому что нет группового повторения как(...){3}
.Хорошо, давайте рассмотрим другой пример, где есть групповое повторение .
Если мы изменим шаблон регулярного выражения , чтобы быть согласованы (для кода , показанных выше) от
(dog(cat(...)(...)(...)))
до(dog(cat(...){3}))
, вы заметите , что существует следующая группа повторение :(...){3}
.Теперь вывод изменился:
Опять же, давайте проанализируем только первое совпадение (
match0
).Больше нет второстепенных групп
group4
иgroup5
из-за(...){3}
повторения ( {n} где n> = 2 ) они были объединены в одну группуgroup3
.В этом случае
group3
значение соответствуетcapture2
( последний захват , другими словами).Таким образом, если вам нужны все 3 внутренних захвата (
capture0
,capture1
,capture2
) , вам придется цикл через группуCaptures
сбор.Вывод: обратите внимание на то, как вы проектируете группы вашего паттерна. Вы должны заранее подумать, какое поведение вызывает спецификацию группы, например
(...)(...)
,(...){2}
и(.{3}){2}
т. Д.Надеюсь, это поможет пролить свет на различия между захватами , группами и матчами .
источник