Индексы групп захвата регулярных выражений Java

113

У меня есть следующая строка,

typeName="ABC:xxxxx;";

Мне нужно достать слово ABC,

Я написал следующий фрагмент кода,

Pattern pattern4=Pattern.compile("(.*):");
matcher=pattern4.matcher(typeName);

String nameStr="";
if(matcher.find())
{
    nameStr=matcher.group(1);

}

Так что, если я ставлю group(0)я , ABC:но если я ставлю group(1)это ABC, так что я хочу знать

  1. Что это 0и 1значит? Будет лучше, если кто-нибудь сможет мне объяснить на хороших примерах.

  2. Шаблон регулярного выражения содержит :в себе символ, так почему group(1)результат его пропускает? Обнаруживает ли группа 1 все слова внутри скобок?

  3. Итак, если я поставлю еще две скобки, например \\s*(\d*)(.*):, тогда будет ли две группы? group(1)вернет (\d*)деталь и group(2)вернет (.*)деталь?

Фрагмент кода был дан, чтобы прояснить мои затруднения. Я имею дело не с кодом. Приведенный выше код можно сделать String.split()гораздо проще.

П басак
источник

Ответы:

182

Захват и группировка

Группа захвата (pattern) создает группу со свойством захвата .

Связанный с этим один , что вы можете часто видеть (и использование) является (?:pattern), что создает группу без захвата собственности, следовательно , названные без захвата группы .

Группа обычно используется, когда вам нужно повторить последовательность шаблонов, например (\.\w+)+, или указать, где должно произойти чередование, например ^(0*1|1*0)$( ^, затем 0*1или 1*0, затем $) по сравнению с ^0*1|1*0$( ^0*1или 1*0$).

Группа захвата, помимо группирования, также записывает текст, соответствующий шаблону внутри группы захвата (pattern). Используя ваш пример, (.*):, .*спички ABCи :спички :, и с тех пор .*находится внутри захвата группы (.*), текст ABCзаписывается для захвата 1 -й группы.

Номер группы

Весь шаблон определяется как номер группы 0.

Любая группа захвата в шаблоне начинает индексирование с 1. Индексы определяются порядком открывающих скобок групп захвата . В качестве примера, вот все 5 групп захвата в следующем шаблоне:

(group)(?:non-capturing-group)(g(?:ro|u)p( (nested)inside)(another)group)(?=assertion)
|     |                       |          | |      |      ||       |     |
1-----1                       |          | 4------4      |5-------5     |
                              |          3---------------3              |
                              2-----------------------------------------2

Номера групп используются в обратной ссылке \nв шаблоне и $nв строке замены.

В других разновидностях регулярных выражений (PCRE, Perl) они также могут использоваться в вызовах подпрограмм .

Вы можете получить доступ к тексту, соответствующему определенной группе, с помощью Matcher.group(int group). Номера групп могут быть идентифицированы с помощью указанного выше правила.

В некоторых разновидностях регулярных выражений (PCRE, Perl) есть функция сброса ветвей, которая позволяет вам использовать один и тот же номер для захвата групп в разных ветвях чередования .

Название группы

В Java 7 вы можете определить именованную группу захвата (?<name>pattern) и получить доступ к соответствующему контенту Matcher.group(String name). Регулярное выражение длиннее, но код более значим, поскольку он указывает, что вы пытаетесь сопоставить или извлечь с помощью регулярного выражения.

Имена групп используются в обратной ссылке \k<name>в шаблоне и ${name}в строке замены.

Именованные группы захвата по-прежнему пронумерованы по той же схеме нумерации, поэтому к ним также можно получить доступ через Matcher.group(int group).

Внутренне реализация Java просто отображает имя в номер группы. Следовательно, вы не можете использовать одно и то же имя для 2 разных групп захвата.

nhahtdh
источник
1
ВОТ ЭТО ДА! Спасибо @nhahtdh за объяснение групп без захвата и того, как работает порядок вложенных групп. Я был в тупике относительно того, как работают номера групп, пока наконец не прочитал ваше объяснение. Большое спасибо!
MMeah 03 фев.15,
92

Для остальных из нас

Вот простой и понятный пример того, как это работает

Регулярное выражение: ([a-zA-Z0-9]+)([\s]+)([a-zA-Z ]+)([\s]+)([0-9]+)

Строка: "!* UserName10 John Smith 01123 *!"

group(0): UserName10 John Smith 01123
group(1): UserName10
group(2):  
group(3): John Smith
group(4):  
group(5): 01123

Как видите, я создал ПЯТЬ групп, каждая из которых заключена в круглые скобки.

Я включил! * И *! с обеих сторон, чтобы было понятнее. Обратите внимание, что ни один из этих символов не входит в RegEx и поэтому не будет отображаться в результатах. Группа (0) просто дает вам всю совпавшую строку (все мои критерии поиска в одной строке). Группа 1 останавливается прямо перед первым пробелом, потому что пробел не был включен в критерии поиска. Группы 2 и 4 - это просто пробел, который в данном случае является буквально пробелом, но также может быть табуляцией или переводом строки и т. Д. Группа 3 включает пробел, потому что я поместил его в критерии поиска ... и т. Д.

Надеюсь, это имеет смысл.

Майкл Симс
источник
1
прекрасный пример, который легко понять новичкам. Я сомневаюсь, что это то же самое, что и группировка reg ex в python? или еще есть разница? Я новичок в reg ex, поэтому я немного запутался в обоих языках.
Mani
1
Это недопустимое регулярное выражение Java: обратная косая черта должна быть удвоена.
Николас Рауль,
1
@NicolasRaoul: Двойная обратная косая черта возникает из-за синтаксиса escape в строковом литерале. Фактический синтаксис регулярного выражения (то есть, если вы выводите строку, содержащую регулярное выражение, на консоль), не требует двойной обратной косой черты.
nhahtdh 06
@NicolasRaoul Если бы вы скопировали и вставили мою строку регулярного выражения в реальный Java-код, используя компетентную среду IDE, среда IDE должным образом отформатировала бы escape-косые черты по мере необходимости. Но мое регулярное выражение технически и синтаксически корректно и служит основной цели - продемонстрировать связь между кодом регулярного выражения и полученными результатами (на очень конкретном примере) ... немного осветить ... ☺
Майкл Симс,
44

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

group(1)Содержит строку, заключенную в круглые скобки (.*)так.* и в этом случае

И group(0) содержит всю совпавшую строку.

Если у вас будет больше групп (читать (...)), они будут помещены в группы со следующими индексами (2, 3 и так далее).

Михал Борек
источник
2
Итак, я прав, добавление скобок на самом деле для создания групп?
P basak
3
Да, можно так сказать.
Михал Борек