Bagaimana kelompok yang tidak menangkap, yaitu (?:)
, digunakan dalam ekspresi reguler dan untuk apa mereka?
regex
capturing-group
regex-group
never_had_a_name
sumber
sumber
Jawaban:
Biarkan saya mencoba menjelaskan ini dengan sebuah contoh.
Pertimbangkan teks berikut:
Sekarang, jika saya menerapkan regex di bawah ini ...
... Saya akan mendapatkan hasil berikut:
Tapi saya tidak peduli dengan protokol - saya hanya ingin host dan path dari URL. Jadi, saya mengubah regex untuk memasukkan grup yang tidak menangkap
(?:)
.Sekarang, hasil saya terlihat seperti ini:
Lihat? Grup pertama belum ditangkap. Parser menggunakannya untuk mencocokkan teks, tetapi mengabaikannya nanti, pada hasil akhir.
EDIT:
Seperti yang diminta, izinkan saya mencoba menjelaskan kelompok juga.
Ya, kelompok melayani banyak tujuan. Mereka dapat membantu Anda untuk mengekstrak informasi yang tepat dari kecocokan yang lebih besar (yang juga bisa disebut), mereka memungkinkan Anda membuat ulang grup yang cocok sebelumnya, dan dapat digunakan untuk pergantian pemain. Mari kita coba beberapa contoh, oke?
Bayangkan Anda memiliki semacam XML atau HTML (perlu diketahui bahwa regex mungkin bukan alat terbaik untuk pekerjaan itu , tetapi itu bagus sebagai contoh). Anda ingin mengurai tag, sehingga Anda dapat melakukan sesuatu seperti ini (saya telah menambahkan spasi untuk membuatnya lebih mudah dimengerti):
Regex pertama memiliki grup bernama (TAG), sedangkan regex kedua menggunakan grup umum. Kedua regex melakukan hal yang sama: mereka menggunakan nilai dari grup pertama (nama tag) untuk mencocokkan tag penutup. Perbedaannya adalah bahwa yang pertama menggunakan nama untuk mencocokkan nilai, dan yang kedua menggunakan indeks grup (yang dimulai pada 1).
Mari kita coba beberapa pergantian sekarang. Pertimbangkan teks berikut:
Sekarang, mari kita gunakan regex bodoh ini di atasnya:
Regex ini cocok dengan kata-kata dengan setidaknya 3 karakter, dan menggunakan grup untuk memisahkan tiga huruf pertama. Hasilnya adalah ini:
Jadi, jika kita menerapkan string substitusi:
... di atasnya, kami mencoba menggunakan grup pertama, tambahkan garis bawah, gunakan grup ketiga, lalu grup kedua, tambahkan garis bawah lain, dan kemudian grup keempat. String yang dihasilkan akan seperti yang di bawah ini.
Anda juga dapat menggunakan grup yang disebut sebagai pengganti, menggunakan
${name}
.Untuk bermain-main dengan regex , saya sarankan http://regex101.com/ , yang menawarkan sejumlah detail tentang cara kerja regex; itu juga menawarkan beberapa mesin regex untuk dipilih.
sumber
Anda dapat menggunakan menangkap grup untuk mengatur dan mengurai ekspresi. Grup yang tidak menangkap memiliki manfaat pertama, tetapi tidak memiliki overhead yang kedua. Anda masih dapat mengatakan bahwa grup yang tidak menangkap adalah opsional, misalnya.
Katakanlah Anda ingin mencocokkan teks numerik, tetapi beberapa angka dapat ditulis sebagai 1, 2, 3, 4, ... Jika Anda ingin mengambil bagian numerik, tetapi bukan sufiks (opsional), Anda dapat menggunakan grup yang tidak menangkap .
Itu akan cocok dengan angka dalam formulir 1, 2, 3 ... atau dalam bentuk 1, 2, 3, ... tetapi itu hanya akan menangkap bagian numerik.
sumber
?:
digunakan ketika Anda ingin mengelompokkan ekspresi, tetapi Anda tidak ingin menyimpannya sebagai bagian string yang cocok / ditangkap.Contohnya adalah sesuatu yang cocok dengan alamat IP:
Perhatikan bahwa saya tidak peduli tentang menyimpan 3 oktet pertama, tetapi
(?:...)
pengelompokan memungkinkan saya untuk mempersingkat regex tanpa mengeluarkan biaya tambahan untuk menangkap dan menyimpan korek api.sumber
Itu membuat grup tidak menangkap, yang berarti bahwa substring yang cocok dengan grup itu tidak akan dimasukkan dalam daftar tangkapan. Contoh dalam ruby untuk menggambarkan perbedaan:
sumber
(?:)
tidak menghasilkan tangkapan, bukan untuk menunjukkan contoh yang bermanfaat(?:)
.(?:)
berguna ketika Anda ingin mengelompokkan sub-ekspresi (misalnya ketika Anda ingin menerapkan quantifiers ke sub-ekspresi non-atom atau jika Anda ingin membatasi ruang lingkup a|
), tetapi Anda tidak ingin menangkap apa pun.MOTIVASI SEJARAH:
Keberadaan kelompok yang tidak menangkap dapat dijelaskan dengan menggunakan tanda kurung.
Pertimbangkan ungkapan-ungkapan
(a|b)c
dana|bc
, karena prioritas rangkaian diakhiri|
, ungkapan-ungkapan ini mewakili dua bahasa yang berbeda ({ac, bc}
dan{a, bc}
masing - masing).Namun, tanda kurung juga digunakan sebagai kelompok yang cocok (seperti yang dijelaskan oleh jawaban lain ...).
Ketika Anda ingin memiliki tanda kurung tetapi tidak menangkap sub-ekspresi Anda menggunakan KELOMPOK NON-CAPTURING. Dalam contoh,
(?:a|b)c
sumber
Biarkan saya coba ini dengan sebuah contoh:
Kode Regex:
(?:animal)(?:=)(\w+)(,)\1\2
Cari String:
Baris 1 -
animal=cat,dog,cat,tiger,dog
Baris 2 -
animal=cat,cat,dog,dog,tiger
Baris 3 -
animal=dog,dog,cat,cat,tiger
(?:animal)
-> Grup Non-Tertangkap 1(?:=)
-> Grup Non-Tertangkap 2(\w+)
-> Grup Yang Ditangkap 1(,)
-> Grup Yang Ditangkap 2\1
-> hasil tangkapan kelompok 1 yaitu Jalur 1 adalah kucing, Baris 2 adalah kucing, Baris 3 adalah anjing.\2
-> hasil tangkapan kelompok 2 yaitu koma (,)Jadi dalam kode ini dengan memberi
\1
dan\2
kami mengingat atau mengulangi hasil dari kelompok yang ditangkap 1 dan 2 masing-masing kemudian dalam kode.Sesuai urutan kode
(?:animal)
harus grup 1 dan(?:=)
harus grup 2 dan berlanjut ..tetapi dengan memberikan
?:
kami membuat kelompok pertandingan tidak ditangkap (yang tidak dihitung dalam kelompok cocok, sehingga nomor pengelompokan dimulai dari kelompok yang ditangkap pertama kali dan bukan yang ditangkap), sehingga pengulangan hasil dari kelompok pertandingan(?:animal)
tidak dapat dipanggil nanti dalam kode.Semoga ini menjelaskan penggunaan kelompok yang tidak menangkap.
sumber
Grup yang menangkap Anda dapat menggunakan nanti di regex untuk mencocokkan ATAU Anda dapat menggunakannya di bagian pengganti regex. Membuat grup yang tidak menangkap cukup mengecualikan grup tersebut dari penggunaan karena salah satu dari alasan ini.
Grup yang tidak menangkap sangat bagus jika Anda mencoba untuk menangkap banyak hal yang berbeda dan ada beberapa kelompok yang tidak ingin Anda tangkap.
Itulah alasan mengapa mereka ada. Saat Anda belajar tentang grup, belajar tentang Grup Atom , mereka melakukan banyak hal! Ada juga kelompok lookaround tetapi mereka sedikit lebih kompleks dan tidak banyak digunakan.
Contoh penggunaan nanti dalam regex (backreference):
<([A-Z][A-Z0-9]*)\b[^>]*>.*?</\1>
[Menemukan tag xml (tanpa dukungan ns)]([A-Z][A-Z0-9]*)
adalah grup penangkap (dalam hal ini adalah tagname)Kemudian dalam regex adalah
\1
yang berarti hanya akan cocok dengan teks yang sama yang ada di grup pertama (([A-Z][A-Z0-9]*)
grup) (dalam hal ini cocok dengan tag akhir).sumber
Yah saya adalah pengembang JavaScript dan akan mencoba menjelaskan maknanya yang berkaitan dengan JavaScript.
Pertimbangkan skenario di mana Anda ingin mencocokkan
cat is animal
ketika Anda ingin mencocokkan kucing dan hewan dan keduanya harus adais
di antara mereka.sumber
Dalam ekspresi reguler yang kompleks, Anda mungkin memiliki situasi timbul di mana Anda ingin menggunakan sejumlah besar kelompok beberapa di antaranya ada untuk pencocokan pengulangan dan beberapa di antaranya ada untuk memberikan referensi kembali. Secara default, teks yang cocok dengan setiap grup dimuat ke dalam array referensi-balik. Di mana kami memiliki banyak grup dan hanya perlu dapat merujuk beberapa dari mereka dari array backreference, kami dapat mengganti perilaku default ini untuk memberi tahu ekspresi reguler bahwa grup tertentu hanya ada untuk penanganan pengulangan dan tidak perlu ditangkap dan disimpan dalam array backreference.
sumber
Saya tidak dapat mengomentari jawaban teratas untuk mengatakan ini: Saya ingin menambahkan titik eksplisit yang hanya tersirat dalam jawaban teratas:
Kelompok non-menangkap
(?...)
tidak tidak menghapus karakter apapun dari pertandingan penuh asli, hanya mereorganisasi regex visual untuk programmer.Untuk mengakses bagian tertentu dari regex tanpa karakter asing yang ditentukan, Anda harus selalu menggunakannya
.group(<index>)
sumber
tl; dr grup yang tidak menangkap, seperti namanya adalah bagian dari regex yang tidak ingin Anda sertakan dalam pertandingan dan
?:
merupakan cara untuk mendefinisikan grup sebagai tidak menangkap.Katakanlah Anda memiliki alamat email
[email protected]
. Regex berikut akan membuat dua grup , bagian id dan bagian @ example.com.(\p{Alpha}*[a-z])(@example.com)
. Demi kesederhanaan, kami mengekstraksi seluruh nama domain termasuk@
karakter.Sekarang katakanlah, Anda hanya perlu bagian id dari alamat. Yang ingin Anda lakukan adalah mengambil grup pertama dari hasil pertandingan, dikelilingi oleh
()
dalam regex dan cara untuk melakukannya adalah dengan menggunakan sintaks grup non-capturing, yaitu?:
. Jadi regex(\p{Alpha}*[a-z])(?:@example.com)
akan mengembalikan hanya bagian id dari email.sumber
Satu hal menarik yang saya temui adalah kenyataan bahwa Anda dapat memiliki grup menangkap di dalam grup yang tidak menangkap. Lihat di bawah ini regex untuk mencocokkan url web:
Masukkan url string:
Grup pertama di regex saya
(?:([A-Za-z]+):)
adalah grup non-menangkap yang cocok dengan skema protokol dan:
karakter titik dua yaituhttp:
tetapi ketika saya menjalankan kode di bawah, saya melihat indeks pertama dari array yang dikembalikan berisi stringhttp
ketika saya memikirkan ituhttp
dan titik dua:
keduanya tidak akan dilaporkan karena mereka berada di dalam kelompok yang tidak menangkap.Saya pikir jika grup pertama
(?:([A-Za-z]+):)
adalah grup yang tidak menangkap maka mengapa ia mengembalikanhttp
string dalam array output.Jadi, jika Anda perhatikan ada grup bersarang
([A-Za-z]+)
di dalam grup yang tidak menangkap. Grup bersarang itu([A-Za-z]+)
adalah grup yang menangkap (tidak memiliki?:
di awal) di dalam dirinya sendiri di dalam grup yang tidak menangkap(?:([A-Za-z]+):)
. Itu sebabnya tekshttp
masih dapat ditangkap tetapi:
karakter titik dua yang ada di dalam grup yang tidak menangkap tetapi di luar grup yang menangkap tidak dilaporkan dalam larik keluaran.sumber
Buka devTools Google Chrome Anda dan kemudian tab Console: dan ketik ini:
Jalankan dan Anda akan melihat:
Mesin
JavaScript
RegExp menangkap tiga grup, item dengan indeks 1,2,3. Sekarang gunakan tanda yang tidak menangkap untuk melihat hasilnya.Hasilnya adalah:
Ini jelas apa yang dimaksud dengan kelompok tidak menangkap.
sumber
Saya pikir saya akan memberi Anda jawabannya. Jangan gunakan variabel penangkapan tanpa memeriksa apakah pertandingan berhasil.
Variabel capture
$1
,, dll, tidak valid kecuali jika pertandingan berhasil, dan mereka juga tidak dihapus.Dalam contoh di atas, untuk menghindari penangkapan bronto
$1
,(?:)
digunakan.Jika polanya cocok, maka
$1
ditangkap sebagai pola yang dikelompokkan berikutnya.Jadi, hasilnya akan seperti di bawah ini:
Ini berguna jika Anda tidak ingin korek api disimpan.
sumber
Ini sangat sederhana, Kita dapat mengerti dengan contoh tanggal sederhana, misalkan jika tanggal tersebut disebutkan sebagai 1 Januari 2019 atau 2 Mei 2019 atau tanggal lainnya dan kami hanya ingin mengubahnya menjadi format dd / mm / yyyy kita tidak memerlukan bulan nama yang Januari atau Februari dalam hal ini, jadi untuk menangkap bagian numerik, tetapi bukan sufiks (opsional) Anda dapat menggunakan grup yang tidak menangkap.
jadi ekspresi regulernya adalah,
Sesederhana itu.
sumber