Saya tidak begitu mengerti ekspresi reguler. Bisakah Anda menjelaskannya kepada saya dengan cara yang mudah diikuti? Jika ada alat atau buku online, dapatkah Anda juga menautkannya?
Bagian terpenting adalah konsep. Setelah Anda memahami bagaimana blok bangunan bekerja, perbedaan dalam jumlah sintaksis sedikit lebih dari dialek ringan. Lapisan di atas sintaks mesin ekspresi reguler Anda adalah sintaks dari bahasa pemrograman yang Anda gunakan. Bahasa seperti Perl menghapus sebagian besar komplikasi ini, tetapi Anda harus mengingat pertimbangan lain jika Anda menggunakan ekspresi reguler dalam program C.
Jika Anda menganggap ekspresi reguler sebagai blok bangunan yang dapat Anda campur dan padankan sesuka Anda, ada baiknya Anda belajar cara menulis dan men-debug pola Anda sendiri, tetapi juga bagaimana memahami pola yang ditulis oleh orang lain.
Secara konseptual, ekspresi reguler paling sederhana adalah karakter literal. Polanya N
cocok dengan karakter 'N'.
Ekspresi reguler di sebelah urutan pertandingan yang sama. Misalnya, polanya Nick
cocok dengan urutan 'N' diikuti oleh 'i' diikuti oleh 'c' diikuti oleh 'k'.
Jika Anda pernah menggunakan grep
Unix — sekalipun hanya untuk mencari string yang tampak biasa — Anda telah menggunakan ekspresi reguler! (The re
dalam grep
mengacu pada ekspresi reguler.)
Menambahkan sedikit kompleksitas, Anda dapat mencocokkan 'Nick' atau 'nick' dengan polanya [Nn]ick
. Bagian dalam tanda kurung siku adalah kelas karakter , yang artinya cocok dengan salah satu karakter terlampir. Anda juga dapat menggunakan rentang dalam kelas karakter, sehingga [a-c]
cocok dengan 'a' atau 'b' atau 'c'.
Polanya .
spesial: daripada mencocokkan titik literal saja, pola ini cocok dengan karakter apa saja † . Itu sama secara konseptual dengan kelas karakter yang sangat besar [-.?+%$A-Za-z0-9...]
.
Pikirkan kelas karakter sebagai menu: pilih satu saja.
Menggunakan .
dapat menghemat banyak mengetik, dan ada cara pintas lainnya untuk pola umum. Katakanlah Anda ingin mencocokkan angka: satu cara untuk menulis itu [0-9]
. Digit adalah target pertandingan yang sering, jadi Anda bisa menggunakan pintasan \d
. Lainnya adalah \s
(spasi putih) dan \w
(karakter kata: alfanumerik atau garis bawah).
Varian huruf besar adalah pelengkap mereka, jadi \S
cocok dengan karakter non- spasi putih, misalnya.
Dari sana, Anda dapat mengulangi bagian dari pola Anda dengan penjumlahan . Misalnya, polanya ab?c
cocok dengan 'abc' atau 'ac' karena ?
quantifier menjadikan subpattern yang dimodifikasi opsional. Pengukur lainnya adalah
*
(nol kali atau lebih)+
(satu kali atau lebih){n}
(tepat n kali){n,}
(setidaknya n kali){n,m}
(setidaknya n kali tetapi tidak lebih dari m kali)Dengan menyatukan beberapa blok ini, polanya [Nn]*ick
cocok dengan semuanya
Pertandingan pertama menunjukkan pelajaran penting: *
selalu berhasil! Pola apa pun bisa cocok dengan nol kali.
Beberapa contoh bermanfaat lainnya:
[0-9]+
(dan yang setara \d+
) cocok dengan bilangan bulat non-negatif\d{4}-\d{2}-\d{2}
tanggal pertandingan diformat seperti 2019-01-01Kuantifikasi mengubah pola ke kiri langsung. Anda mungkin berharap 0abc+0
mencocokkan '0abc0', '0abcabc0', dan sebagainya, tetapi polanya langsung di sebelah kiri quantifier plus adalah c
. Ini berarti 0abc+0
cocok dengan '0abc0', '0abcc0', '0abccc0', dan seterusnya.
Untuk mencocokkan satu atau lebih urutan 'abc' dengan nol di ujungnya, gunakan 0(abc)+0
. Tanda kurung menunjukkan suatu subpattern yang dapat dikuantifikasi sebagai satu unit. Ini juga umum untuk mesin ekspresi reguler untuk menyimpan atau "menangkap" bagian dari teks input yang cocok dengan grup yang di-kurung. Mengekstrak bit dengan cara ini jauh lebih fleksibel dan lebih sedikit kesalahan daripada menghitung indeks dan substr
.
Sebelumnya, kami melihat satu cara untuk mencocokkan 'Nick' atau 'nick'. Lain adalah dengan bergantian seperti pada Nick|nick
. Ingatlah bahwa pergantian mencakup segala sesuatu di sebelah kirinya dan segala sesuatu di sebelah kanannya. Gunakan pengelompokan tanda kurung untuk membatasi ruang lingkup |
, misalnya , (Nick|nick)
.
Sebagai contoh lain, Anda ekuivalen bisa menulis [a-c]
seperti a|b|c
, tapi ini mungkin suboptimal karena banyak implementasi mengasumsikan alternatif akan memiliki panjang lebih besar dari 1.
Meskipun beberapa karakter cocok dengan diri mereka sendiri, yang lain memiliki makna khusus. Pola\d+
tidak cocok dengan garis miring terbalik diikuti oleh huruf kecil D diikuti oleh tanda plus: untuk mendapatkan itu, kita akan gunakan \\d\+
. Sebuah backslash menghapus arti khusus dari karakter berikut.
Pengukur ekspresi reguler adalah serakah. Ini berarti mereka mencocokkan teks sebanyak mungkin sambil membiarkan seluruh pola cocok dengan sukses.
Misalnya, katakan inputnya
"Halo," katanya, "apa kabar?"
Anda mungkin berharap ".+"
untuk mencocokkan hanya 'Halo,' dan kemudian akan terkejut ketika Anda melihat bahwa itu cocok dari 'Halo' sepanjang jalan melalui 'Anda?'.
Untuk beralih dari serakah ke apa yang Anda anggap berhati-hati, tambahkan ekstra ?
ke quantifier. Sekarang Anda mengerti caranya \((.+?)\)
, contoh dari pertanyaan Anda berfungsi. Ini cocok dengan urutan kurung kiri literal, diikuti oleh satu atau lebih karakter, dan diakhiri oleh kurung kanan.
Jika input Anda adalah '(123) (456)', maka tangkapan pertama adalah '123'. Penjumlah non-serakah ingin mengizinkan sisa pola untuk mulai mencocokkan sesegera mungkin.
(Mengenai kebingunganmu, aku tidak tahu dialek ekspresi reguler mana ((.+?))
akan melakukan hal yang sama. Aku curiga ada sesuatu yang hilang dalam transmisi di suatu tempat di sepanjang jalan.)
Gunakan pola khusus ^
untuk mencocokkan hanya di awal input Anda dan $
hanya cocok di akhir. Membuat "bookends" dengan pola Anda di mana Anda berkata, "Saya tahu apa yang ada di depan dan belakang, tetapi berikan saya semuanya di antara" adalah teknik yang berguna.
Katakanlah Anda ingin mencocokkan komentar dari formulir
-- This is a comment --
kamu akan menulis ^--\s+(.+)\s+--$
.
Ekspresi reguler bersifat rekursif, jadi sekarang setelah Anda memahami aturan dasar ini, Anda dapat menggabungkannya sesuka Anda.
†: Pernyataan di atas yang .
cocok dengan karakter apa pun adalah penyederhanaan untuk tujuan pedagogis yang tidak sepenuhnya benar. Dot cocok dengan karakter apa pun kecuali baris baru, "\n"
tetapi dalam praktiknya Anda jarang mengharapkan pola seperti .+
melewati batas baris baru. Perl regex memiliki /s
saklar dan Java Pattern.DOTALL
, misalnya, untuk .
mencocokkan karakter apa pun. Untuk bahasa yang tidak memiliki fitur seperti itu, Anda dapat menggunakan sesuatu seperti [\s\S]
untuk mencocokkan "spasi putih atau non-spasi putih", dengan kata lain apa saja.
a{,m}
bukanlah hal, setidaknya dalam Javascript, Perl, dan Python.