Реггекс 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 просто відображає назву до номера групи. Тому ви не можете використовувати одне ім’я для двох різних груп захоплення.


1
ОЦЕ ТАК! Дякую @nhahtdh за пояснення груп, які не захоплюють, як працює порядок введення груп. Мене спотикали, як працюють номери груп, поки я нарешті не прочитав ваше пояснення. Дуже дякую!
ММаг

92

Для решти нас

Ось простий і зрозумілий приклад того, як це працює

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

Як бачите, я створив П’ятірку груп, які укладені в круглі дужки.

Я включив! * І *! з обох боків, щоб було зрозуміліше. Зауважте, що жоден із цих символів не знаходиться в RegEx, і тому вони не будуть видані в результатах. Група (0) лише дає вам всю відповідну рядок (усі мої критерії пошуку в одному рядку). Група 1 зупиняється безпосередньо перед першим пробілом, оскільки символ пробілу не був включений до критеріїв пошуку. Групи 2 і 4 - це просто пробіл, який у даному випадку є буквально пробільним символом, але також може бути вкладкою або стрічкою рядків і т.д.

Сподіваюся, це має сенс.


1
ідеальний приклад, який легко зрозуміти для початківців. Я сумніваюся, це те саме, що reg ex group у python? чи ще є якась різниця? Я новачок у reg ex, тому я трохи розгублений в обох мовах.
Мані

1
Це не дійсний регулярний вираз Java: зворотні косої риси слід подвоїти.
Ніколя Рауль

1
@NicolasRaoul: Подвійний зворотний косий відрізок зумовлений синтаксисом втечі в прямому рядку. Фактичний синтаксис регулярного вираження (тобто якщо ви друкуєте рядок, що містить регулярний вираз, на консолі) не потребує подвійного нахилу.
nhahtdh

@NicolasRaoul Якщо ви мали б скопіювати та вставити мою рядок регулярного виведення в фактичний код Java за допомогою грамотного IDE, IDE правильно відформатував бланширувальну косу. Але мій Regex є технічно та синтаксично правильним, і він виконує основну мету, яка демонструє зв'язок між кодом регулярного вибору та отриманими результатами (на дуже конкретному прикладі) ... трохи полегшити ... ☺
Майкл Сімс

44

Парентези ()використовуються для угруповання регекс-фраз.

group(1)Містить рядок, між круглими дужками , (.*)так і .*в цьому випадку

І group(0)містить цілі відповідні рядки.

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


2
Отже, я маю рацію, що додавання дужок насправді для створення груп?
P basak

3
Так, ми можемо це сказати.
Міхал Борек
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.