Indeks grup penangkapan ekspresi reguler Java

113

Saya memiliki baris berikut,

typeName="ABC:xxxxx;";

Saya perlu mengambil kata ABC,

Saya menulis potongan kode berikut,

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

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

}

Jadi jika saya taruh group(0)saya dapat ABC:tetapi jika saya taruh group(1)itu ABC, jadi saya ingin tahu

  1. Apa ini 0dan 1artinya? Akan lebih baik jika ada yang bisa menjelaskan kepada saya dengan contoh yang baik.

  2. Pola regex berisi a :di dalamnya, jadi mengapa group(1)hasil menghilangkannya? Apakah grup 1 mendeteksi semua kata di dalam tanda kurung?

  3. Jadi, jika saya beri dua tanda kurung lagi seperti,: \\s*(\d*)(.*)lalu apakah ada dua kelompok? group(1)akan mengembalikan (\d*)bagian tersebut dan group(2)mengembalikan (.*)bagian tersebut?

Potongan kode diberikan dengan tujuan untuk menghilangkan kebingungan saya. Ini bukan kode yang saya hadapi. Kode yang diberikan di atas dapat dilakukan dengan String.split()cara yang lebih mudah.

P basak
sumber

Jawaban:

182

Menangkap dan mengelompokkan

Grup pengambilan (pattern) membuat grup yang memiliki properti penangkapan .

Yang terkait yang mungkin sering Anda lihat (dan gunakan) adalah (?:pattern), yang membuat grup tanpa properti capture , oleh karena itu dinamai non-capturing group .

Grup biasanya digunakan ketika Anda perlu mengulangi urutan pola, misalnya (\.\w+)+, atau untuk menentukan di mana pergantian harus diterapkan, misalnya ^(0*1|1*0)$( ^, kemudian 0*1atau 1*0, kemudian $) versus ^0*1|1*0$( ^0*1atau 1*0$).

Grup penangkap, selain pengelompokan, juga akan merekam teks yang cocok dengan pola di dalam grup penangkap (pattern). Menggunakan contoh Anda (.*):, .*pertandingan ABCdan :pertandingan :, dan karena .*berada di dalam grup penangkap (.*), teks ABCdirekam untuk grup penangkap 1.

Nomor grup

Seluruh pola didefinisikan sebagai nomor kelompok 0.

Grup penangkap dalam pola mulai mengindeks dari 1. Indeks ditentukan oleh urutan kurung buka dari grup penangkap . Sebagai contoh, di sini adalah semua 5 kelompok menangkap di bawah pola:

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

Nomor grup digunakan dalam referensi kembali \ndalam pola dan $ndalam string pengganti.

Dalam ragam regex lainnya (PCRE, Perl), mereka juga dapat digunakan dalam panggilan sub-rutin .

Anda dapat mengakses teks yang cocok dengan kelompok tertentu Matcher.group(int group). Nomor kelompok dapat diidentifikasi dengan aturan yang disebutkan di atas.

Dalam beberapa jenis regex (PCRE, Perl), terdapat fitur reset cabang yang memungkinkan Anda menggunakan nomor yang sama untuk menangkap grup di cabang pergantian yang berbeda .

Nama grup

Dari Java 7, Anda dapat menentukan grup penangkap bernama (?<name>pattern) , dan Anda dapat mengakses konten yang cocok dengannya Matcher.group(String name). Regex lebih panjang, tetapi kodenya lebih bermakna, karena menunjukkan apa yang Anda coba cocokkan atau ekstrak dengan regex.

Nama grup digunakan dalam referensi-belakang \k<name>dalam pola dan ${name}dalam string pengganti.

Grup penangkap bernama masih diberi nomor dengan skema penomoran yang sama, sehingga mereka juga dapat diakses melalui Matcher.group(int group).

Secara internal, implementasi Java hanya memetakan dari nama ke nomor grup. Oleh karena itu, Anda tidak dapat menggunakan nama yang sama untuk 2 grup pengambilan yang berbeda.

nhahtdh
sumber
1
WOW! Terima kasih @nhahtdh karena telah menjelaskan grup yang tidak menangkap tentang cara kerja urutan grup bertingkat. Saya bingung tentang cara kerja nomor kelompok sampai saya akhirnya membaca penjelasan Anda. Terima kasih banyak!
MMeah
92

Untuk Kami

Berikut adalah contoh sederhana dan jelas tentang cara kerjanya

Ekspresi Reguler: ([a-zA-Z0-9]+)([\s]+)([a-zA-Z ]+)([\s]+)([0-9]+)

Tali: "!* UserName10 John Smith 01123 *!"

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

Seperti yang Anda lihat, saya telah membuat LIMA grup yang masing-masing diapit tanda kurung.

Saya menyertakan! * Dan *! di kedua sisi untuk membuatnya lebih jelas. Perhatikan bahwa tidak ada karakter tersebut di RegEx dan oleh karena itu tidak akan dibuat dalam hasil. Grup (0) hanya memberi Anda seluruh string yang cocok (semua kriteria pencarian saya dalam satu baris). Grup 1 berhenti tepat sebelum spasi pertama karena karakter spasi tidak termasuk dalam kriteria pencarian. Grup 2 dan 4 hanyalah spasi kosong, yang dalam hal ini secara harfiah merupakan karakter spasi, tetapi bisa juga berupa tab atau umpan baris, dll. Grup 3 menyertakan spasi karena saya memasukkannya ke dalam kriteria pencarian ... dll.

Semoga ini masuk akal.

Michael Sims
sumber
1
contoh sempurna yang mudah dimengerti untuk pemula. Saya ragu apakah ini sama dengan pengelompokan reg ex di python? atau apakah ada perbedaan? Saya baru mengenal mantan reg. Itu sebabnya saya agak bingung dalam kedua bahasa.
Mani
1
Ini bukan regex Java yang valid: garis miring terbalik harus digandakan.
Nicolas Raoul
1
@NicolasRaoul: Garis miring terbalik ganda disebabkan oleh sintaks escape dalam string literal. Sintaks regex aktual (yaitu jika Anda mencetak string yang berisi regex ke konsol) tidak memerlukan garis miring terbalik ganda.
nhahtdh
@NicolasRaoul Jika Anda menyalin dan menempelkan string regex saya ke dalam kode java yang sebenarnya menggunakan IDE yang kompeten, IDE akan memformat garis miring melarikan diri dengan benar sesuai kebutuhan. Tapi Regex saya secara teknis dan sintaksis benar dan melayani tujuan utama yaitu untuk menunjukkan hubungan antara kode regex dan hasil yang diperoleh (menggunakan contoh yang sangat spesifik) ... meringankan sedikit ... ☺
Michael Sims
44

Tanda kurung ()digunakan untuk mengaktifkan pengelompokan frasa regex.

The group(1)berisi string yang antara kurung (.*)sehingga .*dalam hal ini

Dan group(0)berisi seluruh string yang cocok.

Jika Anda memiliki lebih banyak grup (baca (...)) itu akan dimasukkan ke dalam grup dengan indeks berikutnya (2, 3 dan seterusnya).

Michal Borek
sumber
2
Jadi, saya benar menambahkan tanda kurung sebenarnya untuk membuat grup?
P basak
3
Ya, bisa dibilang begitu.
Michal Borek