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

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

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, поэтому я хочу знать

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

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

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

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

Ответ 1

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

Захват группы (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. Индексы определяются порядком открывающих круглых скобок групп захвата. В качестве примера здесь представлены all 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) существует функция ветвления reset, которая позволяет использовать то же число для групп захвата в разных ветвях чередования.

Имя группы

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

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

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

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

Ответ 2

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

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

Regex: ([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

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

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

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

Ответ 3

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

group(1) содержит строку, которая находится между скобками (.*), поэтому .* в этом случае

И group(0) содержит целую строку со строкой.

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