Regular expression (regex) adalah deretan karakter yang digunakan untuk pencarian string atau teks dengan menggunakan pola (pattern). Anda pasti familiar dengan cara penulisan email, misalnya Kalau kita perhatikan, email memiliki pola : huruf / angka, diikuti oleh tanda @, kemudian diikuti huruf, tanda titik, dan kemudian huruf lagi. Setelah mengetahui pola dari email,
kita bisa mencari potongan teks mana saja yang termasuk email di dalam kumpulan teks yang banyak. Katakanlah kita ingin mencari email di dalam 10 lembar artikel yang tidak mungkin kita telusuri satu persatu secara manual. Email hanya salah satu contoh. Tentu saja, semua teks memiliki pola, mulai dari nomor telpon, nomor KTP, tanggal, dan lain sebagainya. Regex memudahkan kita mencari string tertentu dari teks yang banyak. Dengan regex, kita membuat pola terlebih dahulu. Kemudian
nanti pola ini dicocokkan dengan teks atau tulisan yang panjang. Kalau dijumpai string yang cocok dengan pola, maka string tersebut pun bisa diekstrak atau diambil. Python memiliki modul Perbandingan Mencari Teks Tanpa Regex dan Dengan
Regex Berikut ini kita akan melihat contoh bagaimana mendapatkan nomor telpon tanpa regex, dan akan kita bandingkan dengan menggunakan regex. Katakanlah nomor telpon rumah atau kantor adalah 10 digit, yaitu 3 digit lokasi diikuti oleh spasi dan 7 digit nomor pelanggan (kita misalkan ini hanya untuk kota besar yang memiliki 3 digit kode lokasi). Misalnya adalah nomor 061 7956411. Kita akan membuat sebuah fungsi Tanpa menggunakan regular expression maka jadinya adalah seperti berikut: Bila di jalankan, program di atas akan menampilkan hasil seperti berikut: Fungsi Saat dijalankan program di atas akan menampilkan hasil seperti berikut: Terlihat dari contoh, bahwa untuk mendapatkan nomor telepon, kita memerlukan banyak
baris program. Hal ini sangat tidak efisien. Untuk mengatasinya kita bisa menggunakan regex. Menemukan Pola Teks Menggunakan Regular Expression Program di atas hanya bisa digunakan untuk mencari satu pola nomor telepon, tapi sudah membutuhkan banyak baris program. Bagaimana lagi dengan pola nomor telpon lainnya seperti (061) 7956411 atau tanpa kode daerah 7956411? Program di atas akan gagal memvalidasi nomor telepon tersebut. Regex adalah pola teks.
Misalnya untuk pola digit, kita menggunakan Membuat Objek Regex Sebelum bisa membuat regex di Python terlebih dahulu kita import modul Untuk membuat pola regex, kita menggunakan metode Catatan: Kita sebaiknya menggunakan karakter raw string Mencocokkan Objek Regex Setelah kita membuat objek Bila tidak ada teks yang ditemukan, maka metode search() akan
mengembalikan >>> nomor_telepon_regex = re.compile(r'\d\d\d \d\d\d\d\d\d\d') >>> matching_object = nomor_telepon_regex.search('Nomor telepon saya: 061 7984611') >>> print('Nomor telepon ditemukan: ' + mo.group()) Output dari program di atas adalah seperti berikut: Nomor telepon ditemukan: 061 7984611 Pada contoh di atas, kita membuat objek Ringkasan Penggunaan Regex di Python Langkah – langkah penggunaan regular expression di Python adalah sebagai berikut: 1. Impor modul regular expression
yaitu dengan perintah 2. Buat objek Regex menggunakan metode 3. Lewatkan string ke metode 4. Panggil metode Pengelompokan Menggunakan Tanda Kurung ( ) Misalkan pada nomor telepon 061 7954811, kita ingin memisahkan kode
area 061 dari nomor telepon sisanya. Kita bisa membuat pengelompokan dengan pola Selanjutnya objek string pada group 1 bisa kita panggil menggunakan metode >>> no_telp_regex = re.compile(r'(\d\d\d) (\d\d\d\d\d\d\d)') >>> mo = no_telp_regex.search('Nomor telepon saya .') >>> mo.group() '' >>> mo.group(1) '021' >>> mo.group(2) '8273467' Bila kita ingin mendapatkan hasilnya sekaligus dalam 1 tuple, kita bisa menggunakan metode >>> mo.groups() ('021', '8273467') >>> kode_area, no_telp = mo.groups() >>> print(kode_area) 021 >>> print(no_telp) 8273467 Tanda kurung memiliki arti khusus dalam regex. Bila aslinya yang ingin kita cocokkan adalah tanda kurung, maka kita harus menggunakan karakter escape yaitu dengan tanda \. >>> no_telp_regex = re.compile(r'(\(\d\d\d\)) (\d\d\d\d\d\d\d)') >>> mo = no_telp_regex.search('Nomor telepon saya (021) 8273467.') >>> mo.group(1) '(021)' >>> mo.group(2) '8273467' Karakter escape Mencocokkan Beberapa Kelompok Menggunakan Tanda Pipa | Kita bisa menggunakan tanda pipa Bila kedua string Superman dan Spiderman ada di dalam string yang dicari, maka yang akan dikembalikan adalah yang pertama kali muncul. Perhatikan contoh berikut: >>> hero_regex = re.compile(r'Superman|Spiderman') >>> mo1 = hero_regex.search('Superman and Spiderman') >>> mo1.group() 'Superman' >>> mo2 = hero_regex.search('Spiderman and Superman') >>> mo2.group() 'Spiderman' Kita juga bisa menggunakan
karakter pipa untuk mencocokkan salah satu dari beberapa pola. Misalnya, kita ingin mencocokkan salah satu dari >>> bat_regex = re.compile(r'Bat(man|copter|mobile|bat)') >>> mo = bat_regex.search('Batcopter sedang rusak') >>> mo.group() 'Batcopter' >>> mo.group(1) 'copter' Metode Bila yang kita ingin cocokkan adalah karakter Pencocokan Nol Atau Satu Kali Menggunakan Tanda Tanya ? Tanda tanya bisa digunakan untuk pola opsional. Maksudnya adalah stringnya bisa ada atau tidak. Bisa 0 kali atau 1 kali. Tanda >>> bat_regex = re.compile(r'Bat(wo)?man') >>> mo1 = bat_regex.search('Ada Batman di Gotham city') >>> mo1.group() 'Batman' >>> mo2 = bat_regex.search('Ada Batwoman di Gotham city') >>> mo2.group() 'Batwoman' Bagian Untuk contoh nomor telepon, misalnya kode areanya adalah opsional, maka kita bisa melakukannya seperti berikut: >>> no_telp_regex = re.compile(r'(\d\d\d)?\d\d\d\d') >>> mo1 = no_telp_regex.search('Nomor telepon saya ') >>> mo1.group() >>> mo2 = no_telp_regex.search('Nomor telepon saya adalah 8273467') >>> mo2.group() '8273467' Bila yang kita ingin cocokkan adalah karakter Pencocokan Nol, Satu Atau Beberapa Kali Menggunakan Tanda Bintang * Tanda bintang >>> bat_regex = re.compile(r'Bat(wo)*man') >>> mo1 = bat_regex.search('Ada Batman di Gotham city') >>> mo1.group() 'Batman' >>> mo2 = bat_regex.search('Ada Batwoman di Gotham city') >>> mo2.group() 'Batwoman' >>> mo3 = bat_regex.search('Ada Batman di Gotham city') >>> mo3.group() 'Batwowowoman' Perhatikan bahwa Bila yang kita ingin cocokkan adalah karakter * yang sebenarnya, maka kita harus menggunakan karakter escape untuk tanda bintang, yaitu Pencocokan Satu Atau Beberapa Kali Menggunakan Tanda Tambah + Tanda tambah >>> bat_regex = re.compile(r'Bat(wo)+man') >>> mo1 = bat_regex.search('Ada Batwoman di Gotham city') >>> mo1.group() 'Batwoman' >>> mo2 = bat_regex.search('Ada Batwowowoman di Gotham city') >>> mo2.group() 'Batwowowoman' Regex Bila yang kita ingin cocokkan adalah karakter Pola Berulang Menggunakan Tanda Kurung Kurawal { } Kita bisa menggunakan tanda kurung kurawal untuk membuat pola berulang. Misalnya, regex Kita juga
bisa mengatur perulangannya berapa kali, berapa minimum dan maksimumnya. Regex Selain itu, kita juga bisa mengosongkan angka depan atau belakangnya. Regex Perhatikan contoh berikut: >>> he_regex = re.compile(r'(He){3}') >>> mo1 = he_regex.search('HeHeHe') >>> mo1.group() 'HeHeHe' >>> mo2 = he_regex.search('He') >>> mo2 == None True Pada contoh di atas, Pola Rakus dan Tidak Rakus Regex pada Python secara default bersifat rakus (greedy). Artinya, dalam dua atau lebih situasi yang sesuai, maka regex akan memilih string yang paling panjang. Untuk jelasnya tentang hal ini, perhatikan contoh berikut: >>> rakus_regex = re.compile(r'(He){3,5}') >>> mo = rakus_regex.search('HeHeHeHeHe') >>> mo.group() 'HeHeHeHeHe' Dari contoh di atas, bisa di lihat bahwa objek Match mengembalikan ‘HeHeHeHeHe’ dan bukan ‘HeHeHe’, padahal ‘HeHeHe’ juga adalah yang pertama cocok dengan pola. Untuk membuat regex bersifat tidak rakus (non greedy) atau memilih kecocokan string yang pertama, kita bisa menggunakan tanda tanya di ujung dari group regex. Perhatikan contoh berikut: >>> rakus_regex = re.compile(r'(He){3,5}?') >>> mo = rakus_regex.search('HeHeHeHeHe') >>> mo.group() 'HeHeHe' Pada contoh di atas terlihat, bahwa dengan menambahkan tanda tanya di ujung perulangan regex, kita bisa mencegah sifat rakus dari regex. Perlu diingat bahwa tanda tanya selain untuk mencegah sifat rakus regex, juga bisa digunakan untuk pencocokan opsional nol atau satu kali seperti sudah dijelaskan sebelumnya. Metode findall() Sebelumnya, kita hanya menggunakan metode >>> no_telp_regex = re.compile(r'\d{3} \d{7}') >>> string = 'Rumah: 021 8237371 Kantor: 021 8237432' >>> mo1 = no_telp_regex.search(string) >>> mo1.group() '021 8237371' Bila kita ingin mendapatkan semua string yang cocok, maka kita bisa menggunakan metode >>> string = 'Rumah: 021 8237371 Kantor: 021 8237432' >>> no_telp_regex = re.compile(r'\d{3} \d{7}') #tanpa grup >>> mo = no_telp_regex.findall(string) >>> mo ['021 8237371', '021 8237432'] >>> no_telp_regex = re.compile(r'(\d{3}) (\d{7})') #dengan grup >>> mo = no_telp_regex.findall(string) >>> mo [('021', '8237371'), ('021', '8237432') Kelas Karakter Dari contoh – contoh sebelumnya, kita sudah mengetahui bahwa
Misalkan regex >>> sesuatu_regex = re.compile(r'\d+\s\w+') >>> sesuatu_regex.findall('11 sepeda, 10 mobil, 9 pesawat, 8 komputer, 7 handphone') ['11 sepeda', '10 mobil', '9 pesawat', '8 komputer', '7 handphone' Pada contoh di atas, metode Membuat Karakter Kelas Sendiri Kita bisa mendefinisikan kelas karakter kita sendiri untuk digunakan pada regex. Kita mendefinisikan
kelas karakter yang kita inginkan di dalam tanda [ ]. Seperti misalnya >>> vokal_regex = re.compile(r'[aiueoAIUEO]') >>> vokal_regex.findall('Learning Python is VERY FUN') ['e', 'a', 'i', 'o', 'i', 'E', 'U'] Kelas karakter Kelas karakter Kelas karakter Untuk karakter – karakter kontrol seperti +, ., *, atau () dibuat apa
adanya (tidak menggunakan tanda karakter escape Kita juga bisa membuat kebalikan atau negasi dari kelas karakter dengan menggunakan tanda caret ( >>> konsonan_regex = re.compile(r'[^aiueoAIUEO]') >>> konsonan_regex.findall('Learning Python is VERY FUN') ['L', 'r', 'n', 'n', 'g', ' ', 'P', 'y', 't', 'h', 'n', ' ', 's', ' ', 'V', 'R', 'Y', ' ', 'F', 'N'] Membuat Regex Awal dan Akhir Teks dengan Tanda Caret ^ dan Dollar $ Tanda Tanda Kombinasi Untuk jelasnya, perhatikan contoh berikut ini: >>> awal_hello = re.compile(r'^Hello') >>> akhir_angka = re.compile(r'\d$') >>> angka_semua = re.compile(r'^\d+$') >>> awal_hello.search('Hello World!') <_sre.SRE_Match object; span=(0, 5), match='Hello'> >>> akhir_angka.search('Nomor bus itu adalah 121') <_sre.SRE_Match object; span=(23, 24), match='1'> >>> angka_semua.search('1239876450') <_sre.SRE_Match object; span=(0, 10), match='1239876450'> Pada contoh di atas terlihat bahwa fungsi Karakter Wildcard Karakter titik ( >>> ang_regex = re.compile(r'.ang') >>> ang_regex.findall('Sang Bang mencari barang plang Cap 7ang.') ['Sang', 'Bang', 'rang', 'lang', '7ang'] Perlu diperhatikan bahwa karakter titik hanya cocok dengan satu buah karakter. Oleh karena itu pada contoh di atas, Mencocokkan Keseluruhan String Menggunakan Tanda Titik Bintang .* Kadang kala kita ingin mencocokkan keseluruhan string, karakter apapun yang ada di dalamnya. Misalnya string Keseluruhan string tersebut bisa kita cocokkan menggunakan tanda titik bintang ( Perhatikan contoh berikut ini: >>> name_regex = re.compile(r'Nama Depan: (.*) Nama Belakang: (.*)') >>> mo = name_regex.search('Nama Depan: Budi Nama Belakang: Susanti') >>> mo.group(1) 'Budi' >>> mo.group(2) 'Susanti' Regex titik bintang menggunakan mode rakus (greedy). Regex ini akan mencocokkan string sebanyak mungkin sampai akhir string. Untuk menggunakan mode non-greedy, kita menambahkan tanda tanya menjadi >>> nongreedy_regex = re.compile(r'<.*?>') >>> mo = nongreedy_regex.search('<Budi pergi> ke pasar.>') >>> mo.group() '<Budi pergi>' >>> greedy_regex = re.compile(r'<.*>') >>> mo = greedy_regex.search('<Budi pergi> ke pasar.') >>> mo.group() '<Budi pergi> ke pasar.>' Mencocokkan Karakter Newline Menggunakan Regex titik bintang ( >>> tanpa_newline = re.compile(r'.*') >>> mo = tanpa_newline.search('Python adalah bahasa pemrograman.\nBahasa ini diciptakan oleh Guido van Rossum\nSekarang Python sudah terkenal') >>> mo.group() 'Python adalah bahasa pemrograman' >>> dengan_newline = re.compile(r'.*', re.DOTALL) >>> mo = dengan_newline.search('Python adalah bahasa pemrograman.\nBahasa ini diciptakan oleh Guido van Rossum\nSekarang Python sudah terkenal') >>> mo.group() 'Python adalah bahasa pemrograman.\nBahasa ini diciptakan oleh Guido van Rossum\nSekarang Python sudah terkenal' Review Simbol Regex Sejauh ini, kita sudah mempelajari banyak simbol regex. Berikut adalah tinjauannya:
Pencocokan Case-Insensitive Normalnya, regex mencocokkan string persis sama dengan pola yang dibuat. Huruf besar dan kecil dianggap berbeda (case-sensitive). Jadi Untuk membuat regex yang
case-insensitive, kita bisa menambahkan argumen kedua ke >>> python = re.compile(r'python', re.I) >>> python.search('python is so fun').group() 'python' >>> python.search('Python is so fun').group() 'Python' >>> python.search('PYTHON is so fun').group() 'PYTHON' Mengganti String Menggunakan Metode sub() Regex bisa digunakan untuk mengubah objek yang cocok dengan objek yang lain. Caranya adalah dengan menggunakan metode Metode Perhatikan contoh berikut: >>> name_regex = re.compile(r'Agen \w+') >>> name_regex.sub('SENSOR', 'Agen Bob menyerahkan dokumen rahasia ke Agen Lance.') 'SENSOR menyerahkan dokumen rahasia ke SENSOR.' Ada kalanya kita perlu mengganti bagian tertentu saja dari group string. Misalnya kita ingin menampilkan huruf pertama dari string yang cocok dan menyensor sisanya. Di sini kita bisa mengetikkan \1, \2, \3, dan seterusnya yang berarti “Group 1, 2, 3 biarkan apa adanya, sedangkan yang selanjutnya diganti”. Perhatikan contoh berikut: >>> name_regex = re.compile(r'Agen (\w)\w*') >>> name_regex.sub(r'\1****', 'Agen Bob memberi tahu Agen Suneo bahwa Agen Patrick adalah mata-mata.') 'B**** memberi tahu S**** bahwa P**** adalah mata-mata.' Perhatikan dari contoh di atas, kita membiarkan group 1 tidak digantikan dan yang selainnya digantikan dengan tanda bintang. Mengorganisir Regex Yang Kompleks Kita bisa membuat komentar di dalam Misalnya, regex untuk email seperti berikut: email_regex = re.compile(r'([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+(\.[a-zA-Z]{2,4}))') Regex tersebut bisa kita gantikan dengan yang berikut: email_regex = re.compile(r'''( [a-zA-Z0-9._%+-]+ # username @ # simbol @ [a-zA-Z0-9.-]+ # nama domain (\.[a-zA-Z]{2,4}) # dot-something )''', re.VERBOSE) Pada contoh di atas, tanda # di dalam regex akan diabaikan. Demikian pula dengan karakter kosong (spasi) ekstra di dalam string, akan diabaikan. Cara ini membuat kita lebih mudah mengorganisir regex sehingga lebih mudah dibaca. Menggabungkan re.IGNORCASE, re.DOTALL, dan re.VERBOSE Metode >>> python_regex = re.compile(r'python', re.IGNORECASE | re.DOTALL | re.VERBOSE) |