Ekspresi reguler
Bagaimana kita bisa memastikan bahwa suatu objek Kata
adalah email? Bagaimana kita memastikan bahwa suatu objek Kata
adalah nomor telpon?
Untuk kasus-kasus seperti itu, kita menggunakan sesuatu yang disebut sebagai ekspresi reguler (regular expression).
Ekspresi reguler adalah topik bahasan yang susah difahami dalam sekali baca. Ia juga bukan bahasan yang sederhana. Puluhan buku ditulis untuk membahas topik ini. Jelas, sebagai pemrogram yang handal kita wajib mengetahui apa itu ekspresi regular dan kegunaanya.
Jika pada akhirnya pembaca dapat mengatakan: "oh, untuk validasi apakah email itu betul atau tidak, kita bisa gunakan ekspresi reguler lho..." maka tujuan dari artikel ini dapat dikatakan terpenuhi; yakni, untuk memperkenalkan topik yang ekspresi reguler dan kegunaannya.
Sintaksis
Suatu EkspresiRegular
dibuat menggunakan sintaksis literal sebagai berikut:
#r{<pola ekspresi regular>}
Kita kemudian dapat menggunakan operator =~
untuk mencocokkan apakah suatu Kata
sesuai dengan suatu EkspresiRegular
.
Jangkar: pengawal dan pengakhir
\AGa
mengutus benar jika suatu baris kata diawali dengan kata "Ga"
:
cetak("Gara" =~ #r{\AGa})
cetak("Gabung" =~ #r{\AGa})
cetak("Gajah" =~ #r{\AGa})
cetak("Gagak" =~ #r{\AGa})
cetak("Guru" =~ #r{\AGa})
Karena \A
hanya mencocokkan untuk suatu Kata
yang hanya memiliki satu baris, maka pola ini akan mengutus salah
jika Kata
yang sebenarnya dapat cocok, diawali dengan (\n
), misal:
cetak("\nGara\n" =~ #r{\AGa})
Sedangkan untuk mencocokkan selama akhir kata memenuhi suatu pola, kita menggunakan \z
(z
nya kecil):
cetak("raga" =~ #r{ga\z})
cetak("boga" =~ #r{ga\z})
cetak("toga" =~ #r{ga\z})
cetak("naga" =~ #r{ga\z})
cetak("cagar" =~ #r{ga\z})
Jadi yang perlu diingat:
\A
mencocokkanKata
(tanpa pembaris) yang diawali dengan suatu pola\z
mencocokkanKata
(tanpa pembaris) yang diakhiri dengan suatu pola
Pengulangan — * + ? dan {}
Kita bisa menggunakan *
, +
, ?
dan pola {}
sebagai pola pengulangan. Pengulangan disini bermaksud: seberapa banyak huruf-huruf, angka-angka atau pola-pola yang dapat diterima agar suatu EkspresiRegular
bisa dikatakan cocok.
abc*
cocok jika ada subkata berpola"ab"
kemudian diikuti"c"
sebanyak-banyaknya ataupun tidak sama sekali (misal:"abc"
,"ab"
,"abccccccccc"
)abc+
cocok jika ada subkata berpola"ab"
diikuti minimal satu karakter"c"
(misal:"abc"
,"abcc"
,"abccccccccc"
)abc?
cocok jika ada subkata berpola"ab"
kemudian diikuti dengan ada/tidak-adanya"c"
(misal:"ab"
,"abc"
,"abcc"
)abc{2}
cocok jika ada subkata berpola"ab"
diikuti 2"c"
(misal:"abcc"
)abc{2,}
cocok jika ada subkata berpola"ab"
diikuti minimal 2"c"
(misal:"abcc"
,"abccc"
,"abccccccccc"
)abc{2,5}
cocok jika ada subkata berpola"ab"
diikuti minimal 2"c"
dan maksimal 5"c"
(misal:"abcc"
,"abccc"
,"abccccc"
). Pastikan tidak ada spasi antara2
,,
dan,5
.a(bc)*
cocok jika ada subkata berpola"a"
diikuti"bc"
sebanyak-banyaknya ataupun tidak sama sekali (misal:"a"
,"abc"
,"axyz"
)a(bc){2,5}
cocok jika ada subkata berpola"a"
diikuti minimal 2 dan maksimal 5"bc"
(misal:"a"
,"abcbc"
,"abcbcbc"
). Pastikan tidak ada spasi antara2
,,
dan,5
.
Tentu saja, kita bisa menggabungkan pola pembilang dengan pola jangkar. Misal, suatu ekspresi reguler #r{abc{2}}
akan cocok dengan: "abcc"
, pun "abccc"
ataupun "abcccd"
. Jika kita inginkan agar ia hanya bisa cocok jika diakhiri dengan pola tersebut, maka kita gunakan #r{abc{2}\z}
:
cetak("abcc" =~ #r{abc{2}\z}) // benar
cetak("abccc" =~ #r{abc{2}\z}) // salah
Atau — | dan []
Operator []
digunakan untuk mencocokkan apapun yang ada dalam []
tersebut:
cetak("abcbc" =~ #r{a[bc]})
cetak("ab" =~ #r{a[bc]})
cetak("ac" =~ #r{a[bc]})
cetak("ad" =~ #r{a[bc]}) // salah
Atau, menggunakan |
:
cetak("ab" =~ #r{a(b|c)})
cetak("ac" =~ #r{a(b|c)})
cetak("abc" =~ #r{a(b|c)})
cetak("ad" =~ #r{a(b|c)}) // salah
Tentu saja, kita bisa menggabungkan pola ini dengan pola jangkar dan pola-pola lainnya.
cetak("toga" =~ #r{g(a|u)\z})
cetak("tugu" =~ #r{g(a|u)\z})
cetak("gugur" =~ #r{g(a|u)\z}) // salah
Dengan menggunakan []
kita juga bisa mencocokkan karakter dalam lingkup tertentu:
cetak("abc" =~ #r{[a-z]})
cetak("ABC" =~ #r{[A-Z]})
cetak("aBc" =~ #r{[A-Za-z]})
cetak("0123" =~ #r{[0-9]})
cetak("aBc123" =~ #r{[A-Za-z0-9]})
Jika []
diawali dengan ^
, maka berarti tidak. Misal: [^a-z]
berarti apapun yang tidak dari "a"
hingga "z"
.
Kelas
Ekspresi reguler juga memiliki beberapa kelas:
\d
cocok dengan satu digit angka0
,1
,2
,3
hingga9
(sama seperti0-9
dalam[0-9]
)\w
cocok dengan satu karakter alfabet, angka, dan juga tanda hubung_
\s
cocok dengan satu karakter spasi (termasuktab
(\t
) dan karakter pembaris (\n
)).
cocok dengan karakter apapun\D
kebalikan dari\d
, cocok dengan apapun selain angka (sama seperti^0-9
dalam[^0-9]
)\W
kebalikan dari\w
\S
kebalikan dari\s
Karakter lepas
Ekspresi reguler juga memiliki karakter lepasnya. Karakter-karakter ^
, .
, [
, $
, (
, )
, |
, *
, +
, ?
memiliki arti spesial, seperti yang telah kita bahas. Oleh karenanya, untuk mencocokkan karakter-karakter tersebut, kita perlu menggunakan karakter lepasnya, yang diawali dengan tanda \
.
Misal:
- Karakter lepas
.
adalah\.
yang akan mencocokkan dengan suatu titik (bukan karakter apapun, jika hanya.
) - Karakter lepas
^
adalah\^
- Karakter lepas
[
adalah\[
Ada juga karakter lepas \n
untuk pembaris, \t
untuk tab, dan \r
untuk carriage return.
Batas
Setelah mengetahui karakter jangkar seperti \A
dan \z
, sekilas \b
akan memiliki tingkah laku yang mirip dengan jangkar, namun sebenarnya sangat berbeda.
Katakanlah, kita memiliki sebuah Kata
sebagai berikut:
ab abc abcc babc
Kita ingin mengecek apakah kata tersebut memiliki subkata "abc"
secara utuh dan bulat; dalam artian, tidak sebagian seperti "ab"
, atau tidak berlebihan seperti "abcc"
maupun "babc"
. Dalam kasus ini, kita bisa menggunakan pembatas \b
: #r{\babc\b}
\b
dalam artian teknisnya akan cocok dengan suatu subkata yang pada posisi tersebut, satu sisi adalah suatu karakter layaknya \w
, sedangkan sisi lainnya adalah non-karakter seperti spasi ataupun awal dari suatu kata. Itulah kenapa karakter \b
disebut pembatas (boundary), karena ia akan mencocokkan secara penuh dan utuh suatu subkata jika ia diapit diantara 2 \b
seperti dalam contoh \babc\b
.
Kebalikannya, juga terdapat \B
, yang akan cocok dalam semua kondisi dimana \b
tidak cocok, alias \B
adalah negasi atau kebalikan \b
. Dengan begitu, pola ekspresi reguler \Babc\B
akan cocok jika subkata tersebut diapit oleh karakter-karakter kata lainnya.
Ekspresi yang tidak didukung
Gara tidak mendukung tiga jenis ekspresi yang didukung oleh beberapa bahasa lainnya. Ketiga jenis ekspresi tersebut adalah:
- Kilas balik (back-reference):
\1
,\2
,\3
. - Lihat depan (look ahead):
?=
,?!
- Lihat belakang (look behind):
?<=
,?<!
Pola yang menggunakan ketiga ekspresi diatas kebanyakan tidak dapat diselesaikan dalam waktu linear (O(n)
). Oleh karenanya, Gara tidak berencana untuk mendukung ketiga ekspresi tersebut.
Juga, suatu ekspresi reguler akan jauh lebih rumit untuk dapat difahami ketika ia menggunakan salah satu pola diatas.
Selain itu, ekspresi reguler, dari namanyapun, bisa ditebak bahwa kegunaannya adalah untuk hal-hal yang bersifat reguler. Jika kita menggunakan kilas balik untuk melakukan pencocokan, maka sudah jelas itu sudah diluar ranah regular grammar (tata bahasa reguler).
Namun, beberapa bahasa seperti Perl, PHP dan Ruby memang memiliki kemampuan untuk melakukan ketiga hal diatas.
Ekspresi-ekspresi umum
Email
Kode ekspresi reguler berikut akan cocok dengan email yang bisa dikatakan valid.
#r{\b[\w.!#$%&’*+\/=?^`{|}~-]+@[\w-]+(?:\.[\w-]+)*\b}
IPv4
Kode ekspresi reguler berikut akan cocok dengan alamat IPv4
#r{\b(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\b}
URL
Kode ekspresi reguler berikut akan cocok dengan URL yang bisa dikatakan valid.
#r{^(((h..ps?|f.p):\/\/)?(?:([\w\-\.])+(\[?\.\]?)([\w]){2,4}|(?:(?:25[0–5]|2[0–4]\d|[01]?\d\d?)\[?\.\]?){3}(?:25[0–5]|2[0–4]\d|[01]?\d\d?)))*([\w\/+=%&_\.~?\-]*)$}