Pertanyaan Apa itu kelompok yang tidak menangkap? Apa yang (? :) lakukan?


Bagaimana ?: digunakan dan apa gunanya?


1320
2017-08-18 13:17


asal


Jawaban:


Biarkan saya mencoba menjelaskan ini dengan sebuah contoh.

Pertimbangkan teks berikut:

https://stackoverflow.com/
https://stackoverflow.com/questions/tagged/regex

Sekarang, jika saya menerapkan regex di bawah ini ...

(https?|ftp)://([^/\r\n]+)(/[^\r\n]*)?

... Saya akan mendapatkan hasil sebagai berikut:

Match "https://stackoverflow.com/"
     Group 1: "http"
     Group 2: "stackoverflow.com"
     Group 3: "/"

Match "https://stackoverflow.com/questions/tagged/regex"
     Group 1: "http"
     Group 2: "stackoverflow.com"
     Group 3: "/questions/tagged/regex"

Tapi saya tidak peduli dengan protokol - saya hanya ingin host dan path dari URL. Jadi, saya mengubah regex untuk memasukkan grup yang tidak menangkap (?:).

(?:https?|ftp)://([^/\r\n]+)(/[^\r\n]*)?

Sekarang, hasil saya terlihat seperti ini:

Match "https://stackoverflow.com/"
     Group 1: "stackoverflow.com"
     Group 2: "/"

Match "https://stackoverflow.com/questions/tagged/regex"
     Group 1: "stackoverflow.com"
     Group 2: "/questions/tagged/regex"

Lihat? Kelompok pertama belum ditangkap. Parser menggunakannya untuk mencocokkan teks, tetapi kemudian mengabaikannya, di hasil akhir.


EDIT:

Seperti yang diminta, izinkan saya mencoba menjelaskan kelompok juga.

Nah, kelompok melayani banyak tujuan. Mereka dapat membantu Anda untuk mengekstrak informasi yang tepat dari pertandingan yang lebih besar (yang juga dapat disebutkan namanya), mereka membiarkan Anda pertandingan ulang grup yang cocok sebelumnya, dan dapat digunakan untuk substitusi. Mari coba beberapa contoh, ya?

Ok, bayangkan Anda memiliki semacam XML atau HTML (ketahuilah itu regex mungkin bukan alat terbaik untuk pekerjaan itu, tapi ini bagus sebagai contoh). Anda ingin menguraikan tag, sehingga Anda dapat melakukan sesuatu seperti ini (saya telah menambahkan spasi agar lebih mudah dipahami):

   \<(?<TAG>.+?)\> [^<]*? \</\k<TAG>\>
or
   \<(.+?)\> [^<]*? \</\1\>

Regex pertama memiliki grup bernama (TAG), sedangkan yang kedua menggunakan grup umum. Kedua regexes melakukan hal yang sama: mereka menggunakan nilai dari grup pertama (nama tag) untuk mencocokkan tag penutup. Perbedaannya adalah yang pertama menggunakan nama untuk mencocokkan nilai, dan yang kedua menggunakan indeks grup (yang dimulai pada 1).

Mari kita coba beberapa substitusi sekarang. Pertimbangkan teks berikut:

Lorem ipsum dolor sit amet consectetuer feugiat fames malesuada pretium egestas.

Sekarang, mari gunakan regex bodoh ini di atasnya:

\b(\S)(\S)(\S)(\S*)\b

Regex ini mencocokkan kata-kata dengan setidaknya 3 karakter, dan menggunakan grup untuk memisahkan tiga huruf pertama. Hasilnya adalah ini:

Match "Lorem"
     Group 1: "L"
     Group 2: "o"
     Group 3: "r"
     Group 4: "em"
Match "ipsum"
     Group 1: "i"
     Group 2: "p"
     Group 3: "s"
     Group 4: "um"
...

Match "consectetuer"
     Group 1: "c"
     Group 2: "o"
     Group 3: "n"
     Group 4: "sectetuer"
...

Jadi, jika kita menerapkan string substitusi ...

$1_$3$2_$4

... di atasnya, kami mencoba menggunakan grup pertama, tambahkan garis bawah, gunakan grup ketiga, lalu grup kedua, tambahkan garis bawah lain, dan kemudian kelompok keempat. String yang dihasilkan akan seperti yang di bawah ini.

L_ro_em i_sp_um d_lo_or s_ti_ a_em_t c_no_sectetuer f_ue_giat f_ma_es m_la_esuada p_er_tium e_eg_stas.

Anda dapat menggunakan grup bernama untuk penggantian juga, menggunakan ${name}.

Untuk bermain-main dengan regexes, saya sarankan http://regex101.com/, yang menawarkan banyak detail tentang bagaimana regex bekerja; itu juga menawarkan beberapa mesin regex untuk dipilih.


1828
2017-08-18 15:39



Anda dapat menggunakan grup penangkap untuk mengatur dan menguraikan ekspresi. Kelompok yang tidak menangkap memiliki manfaat pertama, tetapi tidak memiliki overhead yang kedua. Anda masih dapat mengatakan 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 menangkap bagian numerik, tetapi bukan akhiran (opsional) Anda dapat menggunakan grup yang tidak menangkap .

([0-9]+)(?:st|nd|rd|th)?

Itu akan mencocokkan angka dalam formulir 1, 2, 3 ... atau dalam bentuk 1, 2, 3, ... tetapi itu hanya akan menangkap bagian numerik.


135
2017-08-18 13:24



?: digunakan ketika Anda ingin mengelompokkan ekspresi, tetapi Anda tidak ingin menyimpannya sebagai bagian string yang cocok / diambil.

Contohnya adalah sesuatu yang cocok dengan alamat IP:

/(?:\d{1,3}\.){3}\d{1,3}/

Perhatikan bahwa saya tidak peduli tentang menyimpan 3 oktet pertama, tetapi (?:...) pengelompokan memungkinkan saya untuk memendekkan regex tanpa menimbulkan overhead menangkap dan menyimpan kecocokan.


87
2017-08-18 13:22



Itu membuat grup tidak menangkap, yang berarti bahwa substring yang dicocokkan oleh grup itu tidak akan dimasukkan dalam daftar penangkapan. Contoh di ruby ​​untuk menggambarkan perbedaannya:

"abc".match(/(.)(.)./).captures #=> ["a","b"]
"abc".match(/(?:.)(.)./).captures #=> ["b"]

27
2017-08-18 13:23



MOTIVASI SEJARAH: Keberadaan kelompok yang tidak dapat menangkap dapat dijelaskan dengan penggunaan tanda kurung. Pertimbangkan ekspresi (a | b) c dan a | bc, karena prioritas penggabungan lebih dari |, ekspresi ini mewakili dua bahasa yang berbeda ({ac, bc} dan {a, bc} masing-masing). Namun, kurung juga digunakan sebagai grup yang cocok (seperti yang dijelaskan oleh jawaban lain ...).

Bila Anda ingin memiliki tanda kurung tetapi tidak menangkap subekspresi, Anda menggunakan GRUP NON-CAPTURING. Dalam contoh, (?: A | b) c


13
2018-02-04 08:07



Kelompokkan itu menangkap Anda dapat menggunakan nanti di regex untuk dicocokkan ATAU Anda dapat menggunakannya di bagian pengganti regex. Membuat a tidak menangkap grup cukup mengecualikan grup tersebut agar tidak digunakan karena salah satu alasan ini.

Grup yang tidak menangkap sangat bagus jika Anda mencoba menangkap banyak hal berbeda dan ada beberapa grup yang tidak ingin Anda tangkap.

Itu cukup banyak alasan mereka ada. Saat Anda belajar tentang grup, pelajari Kelompok Atom, mereka melakukan banyak hal! Ada juga kelompok mencari tahu tetapi mereka sedikit lebih kompleks dan tidak digunakan begitu banyak.

Contoh penggunaan nanti di 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 di dalam regex adalah \1 yang berarti itu hanya akan cocok dengan teks yang sama yang ada di grup pertama (yang ([A-Z][A-Z0-9]*) grup) (dalam hal ini cocok dengan tag akhir).


12
2017-08-18 13:22



Biarkan saya mencoba ini dengan sebuah contoh: -

Kode Regex: - (?:animal)(?:=)(\w+)(,)\1\2

String Pencarian: -

Jalur 1 - hewan = kucing, anjing, kucing, harimau, anjing

Jalur 2 - hewan = kucing, kucing, anjing, anjing, harimau

Jalur 3 - hewan = anjing, anjing, kucing, kucing, harimau

(?:animal) -> Kelompok Tidak Diambil 1

(?:=)-> Grup Tidak Ada Tangkap 2

(\w+)-> Captured Group 1

(,)-> Captured Group 2

\1 -> hasil dari kelompok yang ditangkap 1 yaitu. Dalam Jalur 1 adalah kucing, In Line 2 adalah kucing, In Line 3 adalah anjing.

\2 -> hasil dari kelompok yang ditangkap 2 yaitu koma (,)

Jadi dalam kode ini dengan memberikan \ 1 dan \ 2 kita ingat atau ulangi hasil dari kelompok yang ditangkap 1 dan 2 masing-masing kemudian dalam kode.

Sesuai urutan kode (?: Hewan) harus grup 1 dan (?: =) Harus grup 2 dan berlanjut ..

tetapi dengan memberikan: kami membuat grup pertandingan yang tidak diambil (yang tidak dihitung dalam grup yang cocok, sehingga nomor pengelompokan dimulai dari grup yang pertama diambil dan bukan yang tidak ditangkap), sehingga pengulangan hasil pertandingan -group (?: animal) tidak bisa dipanggil nanti dalam kode.

Semoga ini menjelaskan penggunaan kelompok yang tidak menangkap.

masukkan uraian gambar di sini


8
2018-01-19 11:36



Saya adalah pengembang JavaScript dan akan mencoba untuk menjelaskan signifikansinya terkait dengan JavaScript.

Pertimbangkan skenario di mana Anda ingin mencocokkan cat is animal ketika Anda ingin mencocokkan kucing dan hewan dan keduanya harus memiliki is di antara mereka.

 // this will ignore "is" as that's is what we want
"cat is animal".match(/(cat)(?: is )(animal)/) ;
result ["cat is animal", "cat", "animal"]

 // using lookahead pattern it will match only "cat" we can
 // use lookahead but the problem is we can not give anything
 // at the back of lookahead pattern
"cat is animal".match(/cat(?= is animal)/) ;
result ["cat"]

 //so I gave another grouping parenthesis for animal
 // in lookahead pattern to match animal as well
"cat is animal".match(/(cat)(?= is (animal))/) ;
result ["cat", "cat", "animal"]

 // we got extra cat in above example so removing another grouping
"cat is animal".match(/cat(?= is (animal))/) ;
result ["cat", "animal"]

6
2018-03-01 09:43