0
REGULAR EXPRESSION
Posted by jujur
on
3:48 PM
Regex merupakan singkatan dari Regular
Expression, yaitu sebuah metode untuk mencari suatu pola dalam sebuah string.
Regex sendiri sebenarnya juga merupakan string. Hanya saja karakter dalam
string tersebut diterjemahkan sebagai suatu pola dan aturan tertentu. Misalkan,
string yang diawali oleh tanda caping “^” berarti string tersebut harus diawali
oleh karakter yang mengikuti tanda caping tersebut.
Syntax regex pada setiap bahasa pemrograman
berbeda-beda. Dalam PHP, awalnya dikenal fungsi ereg(), eregi(),
ereg_replace(), dan eregi_replace(), untuk memanfaatkan regex ini. Namun
fungsi-fungsi tersebut sudah tidak dapat digunakan lagi sejak PHP versi 5.3.0
karena sudah diimplementasikan lagi fungsi yang lebih baik lagi.
Fungsi preg_match()
untuk menggunakan regex. Fungsi lainnya yang tersedia adalah preg_replace(),
preg_filter(), preg_match_all(), dan preg_split(). Semuanya terletak dalam
library pcre.php. PCRE adalah singkatan dari Perl Compatible Regular
Expression, yang artinya regex ini dapat digunakan pula pada bahasa pemrograman
Perl. Untuk lebih lengkapnya, Anda bisa mempelajari dokumentasi di website
resminya.
Secara default, pola
yang akan dicari harus diawali dan diakhiri oleh karakter garis miring (slash)
yang berfungsi sebagai delimeter. Contoh Regex paling sederhana untuk mencari
apakah ada pola “fgh” dalam string “abcdefghijk” sebagai berikut.
1
2
3
4
5
6
7
8
|
<?php
$string = 'abcdefghijk';
if(preg_match("/fgh/", $string)) {
echo 'String berisi pola fgh';
} else {
echo 'Tidak ada pola fgh dalam string';
}
?>
|
Berikut ini adalah
beberapa aturan - aturan dan penggunaan regex
sebagai dasar pembuatan regex :
1)
Karakter Awal
Untuk mencari pola “berawalan suatu string”,
maka regex yang digunakan adalah karakter caping “^”. Contohnya, apakah string
berawalan “abc” maka regex-nya adalah sebagai berikut.
1
2
3
4
5
6
7
8
|
<?php
$string = 'abcdefghijk';
if(preg_match("/^abc/", $string)) {
echo 'String berawalan abc';
} else {
echo 'Tidak berawalan abc';
}
?>
|
Tanda caping yang
diikuti karakter abc berarti bahwa string harus berawalan dengan abc. Sedangkan
tanda slash berikutnya menandakan bahwa karakter setelahnya tidak perlu
dihiraukan
2) Case-Sensitive
Namun regex tersebut
tidak berlaku jika satu atau lebih karakter abc pada awal string yang akan
dicari merupakan huruf kapital. Terkadang kita hanya perlu mencari pola
karakter tersebut, tanpa memperhitungkan besar kecilnya. Untuk tidak menghiraukan
case sensitivity, kita bisa menambahkan delimeter “/i” di belakang regex,
menjadi seperti berikut.
1
2
3
4
5
6
7
8
|
<?php
$string = 'abcdefghijk';
if(preg_match("/^ABC/i", $string)) {
echo 'String berawalan abc';
} else {
echo 'Tidak berawalan abc';
}
?>
|
Dengan demikian,
kapital atau tidaknya pola yang dicari tidak akan berpengaruh.
3)
Karakter Akhir
Berikutnya adalah mencari string dengan akhir berupa pola
tertentu. Untuk mencari pola di akhir sebuah string, ada 2 cara. Cara pertama
adalah menggunakan tanda dolar “$”. Namun cara ini memiliki sebuah celah kecil
untuk timbul suatu bug dalam program kita jika tidak digunakan secara benar.
Sebab tanda dolar memasukkan endline “\n” ke dalam pola yang dicari, sehingga
bila mencari pola “xyz” dalam string “abcxyz” dan “abcxyz\n” akan menghasilkan
nilai yang sama-sama benar. Untuk tidak memasukkan endline dalam pola, kia bisa
menggunakan regex backslash z “\z”. Contoh penggunaannya sebagai berikut.
1
2
3
4
5
6
7
8
|
<?php
$string = 'abc123xyz';
if(preg_match("/xyz\z/i", $string)) {
echo 'Pola berakhiran xyz ditemukan';
} else {
echo 'Pola tidak ditemukan';
}
?>
|
Ingat kembali bahwa
“/i” hanya menandakan bahwa regex tersebut case insensitive. Karakter awal dari
string juga tidak akan dihiraukan selama string tersebut memiliki akhiran yang
sesuai.
4)
Meta Characters
Untuk pencarian pola yang mengandung karakter meta, perlu
diberikan perlakuan tersendiri. Karakter meta adalah karakter yang digunakan
sebagai penanda Regex. Seperti contoh sebelumnya, salah satu contoh karakter
meta adalah “^” dan “$”. Selain itu, beberapa karakter lainnya adalah titik
“.”, asterik “*”, plus “+”, tanda tanya “?”, seluruh jenis tanda kurung, pipe
“|”, dan backslash “\”.
Karena merupakan karakter meta, karakter ini tidak akan dibaca
sebagai pola, melainkan hanya sebuah tanda operasi. Untuk memasukkannya sebagai
karakter yang dicari dalam pola, kita harus menambahkan karakter backslash “\”
sebelum karakter meta. Backslash disebut juga sebagai escape character.
Sebagai contoh, jika mencari pola 2+7 dalam sebuah string, maka
bisa ditulis sebagai berikut.
1
2
3
4
5
6
7
8
9
|
<?php
$string = '2+7=9';
if(preg_match("/^2\+7/i", $string)) {
echo 'Pola 2+7 ditemukan';
}
else {
echo 'Tidak ditemukan';
}
?>
|
Perhatikan bahwa
sebelum tanda tambah disertakan pula tanda backslash. Hal ini juga berlaku
untuk semua karakter meta. Pengecualian untuk karakter backslash sendiri karena
escape karakter juga perlu di-escape juga, untuk memasukkan pola backslash pada
regex, maka harus diulang 4 kali menjadi “\\\\”.
5)
Kurung Siku
Karakter kurung siku “[]” merupakan regex untuk menyatakan kelas
karakter, yaitu kumpulan karakter yang diinginkan. Karakter tersebut dapat
dituliskan [abcdefg] atau dengan dash [a-g] khusus untuk karakter yang
berurutan. Untuk melihat apa saja karakter yang sesuai, kita bisa menggunakan
fungsi preg_match_all() dan memasukkan parameter ketiga berupa variable yang
nantinya akan menyimpan sub-string apa saja yang sesuai dengan pola yang
ditentukan.
1
2
3
4
5
6
7
8
9
|
<?php
$string = 'abcefghijklmnopqrstuvwxyz0123456789';
preg_match_all("/[a-f]/", $string, $matches);
foreach($matches[0] as $value) {
echo $value . '<br />';
}
?>
|
Hampir semua karakter
meta tidak akan berfungsi sebagai karakter meta jika di dalam kurung siku ini,
melainkan hanya menjadi karakter biasa. Sehingga bila ingin mencari pola yang
mengandung huruf a, b, c, dan $, maka cukup menuliskannya [abc$] saja, tanpa
escape character.
Pengecualian untuk
karakter caping “^”. Jika diletakkan di awal kurung, itu berarti bahwa yang
dicari adalah karakter yang bukan dalam kurung siku tersebut. Sebagai contoh,
jika ingin mencari pola selain huruf “bgjk” dalam string, maka harus ditulis
sebagai berikut.
1
2
3
4
5
6
7
8
9
|
<?php
$string = 'abcefghijklmnopqrs';
preg_match_all("/[^bgjk]/", $string, $matches);
foreach($matches[0] as $value) {
echo $value . '<br />';
}
?>
|
6)
Titik
Titik juga merupakan karakter meta yang berarti akan
mengembalikan nilai true untuk semua karakter selain line break (\r dan \n),
namun hanya satu karakter. Contohnya adalah sebagai berikut.
1
2
3
4
5
6
7
8
|
<?php
$string = 'helo hilo h lo hxlo hbelo';
if(preg_match_all("/h.lo/", $string, $match)) {
foreach($match[0] as $m) {
echo $m . '<br />';
}
}
?>
|
Program tersebut akan
mencetak kata “helo”, “hilo”, “h lo”, dan “hxlo”, tanpa kata terakhir. Untuk
memasukkan line break dalam aturan, Anda harus memberikan flag “\s” di akhir
regex, sama seperti cara penulisan case insensitive.
7)
Bintang dan Tambah
Tanda bintang “*” dan tambah “+” memiliki arti yang hampir sama.
Dalam regex, tanda bintang diletakkan setelah sebuah karakter, yang artinya
karakter tersebut dapat ada nol atau lebih perulangan yang diharapkan dalam
pola. Sedangkan untuk tanda tambah, itu berarti harus ada satu atau lebih
(tidak boleh nol) karakter yang ditulis dalam aturan. Misalkan, dalam contoh
program berikut.
1
2
3
4
5
6
7
8
9
10
11
|
<?php
$string = array('rby', 'ruby', 'ruuuby');
foreach($string as $s) {
if(preg_match("/ru*by/", $s)) {
echo 'Match ru*by '.$s.'<br
/>';
}
if(preg_match("/ru+by/", $s)) {
echo 'Match ru+by '.$s.'<br
/>';
}
}
?>
|
Program tersebut akan
menghasilkan output:
1
2
3
4
5
|
Match ru*by rby
Match ru*by ruby
Match ru+by ruby
Match ru*by ruuuby
Match ru+by ruuuby
|
Terlihat jelas bahwa
string pertama (rby) tidak akan diterima oleh regex tanda tambah, melainkan
hanya tanda bintang. Tanda tambah setelah huruf u berarti bahwa minimal ada
satu huruf u.
8)
Tanda Tanya
Tanda tanya “?” merupakan karakter meta untuk aturan regex yang
berarti karakter tersebut opsional, boleh ada boleh tidak. Salah satu contoh
kasus penggunaan karakter ini adalah untuk mendeteksi nomer telepon. Kadang ada
yang memasukkan kode area dengan pemisah karakter minux “-“, kadang ada yang
tidak. Sebagai contoh, dalam program berikut.
1
2
3
4
5
6
7
8
|
<?php
$telp = '0857-111111';
if(preg_match("/0857-?111111/", $telp)) {
echo 'Nomer telp benar';
} else {
echo 'Nomer telp salah';
}
?>
|
Seandainya pun
karakter minus dihapus, pola tersebut masih diterima oleh regex karena tanda
minus bersifat opsional.
9)
Kurung Kurawal
Kurung kurawal “{}” merupakan karakter meta yang melambangkan
jumlah karakter atau pola yang harus ada. Biasanya kurung kurawal disertakan
setelah kurung siku, yang berarti harus terdapat beberapa karakter yang
terdapat dalam kurung siku, sejumlah angka yang tertulis di kurung kurawal.
Sebagai contoh, misalkan dalam suatu nomer telepon harus terdapat pola angka
nol sebanyak tiga kali, maka penulisan programnya sebagai berikut.
1
2
3
4
5
6
7
8
|
<?php
$telp = '0341000123';
if(preg_match("/03410{3}123/", $telp)) {
echo 'Nomer telp benar';
} else {
echo 'Nomer telp salah';
}
?>
|
Kita juga bisa
mengkombinasikannya dengan karakter meta yang lain. Sebagai contoh untuk
mendeteksi format nomor telepon rumah Kota Malang yang terdiri atas kode area
0341 dan diikuti oleh 6 angka berikutnya, maka regex-nya adalah sebagai
berikut.
1
2
3
4
5
6
7
8
|
<?php
$telp = '0341-000123';
if(preg_match("/0341-?[0-9]{6}$/", $telp)) {
echo 'Nomer telp Malang';
} else {
echo 'Nomer telp salah';
}
?>
|
Untuk membuat aturan
minimal sejumlah x perulangan, maka kita bisa menuliskannya dengan diikuti
tanda koma setelah angka yang diharapkan. Contohnya, bila ingin terdapat angka
minimal 3 digit, maka dapat ditulis “[0-9]{3,}”. Sedangkan bila menginginkan
rentang jumlah perulangan yang diharapkan, kita dapat menyertakan tambahan
angka lain setelah tanda koma, seperti {3,6} yang berarti jumlah perulangan
harus antara 3 sampai 6 kali.
10)
Urutan Karakter Khusus
Alfabet dan angka merupakan karakter khusus yang berurutan.
Cukup merepotkan bukan bila harus menulis [abcd sampai xyz] ataupun [a-z]? Sama
seperti format lainnya, dalam regex juga dikenal escape character khusus untuk
alfabet, angka, dan linebreak. Berikut ini adalah daftar urutan karakter khusus
yang berlaku pada regex.
·
\d – Untuk seluruh
karakter berupa angka, sama seperti [0-9]
·
\D – Untuk seluruh
karakter yang bukan angka, sama seperti [^0-9]
·
\s – Untuk karakter
whitespace, sama seperti penulisan [\t\r\n\f\v]
·
\S – Untuk karakter
non whitespace, sama seperti penulisan [^\t\r\n\f\v]
·
\w – Untuk semua
karakter alpha-numeric, yaitu alfabet dan angka, sama seperti [a-zA-Z0-9_]
·
\W – Untuk semua
karakter non alpha-numeric, sama seperti [^a-zA-Z0-9_]
Contoh penggunaannya
sebagai berikut. Misalkan kita sedang mencari string dengan pola yang diawali
sebuah angka, kemudian 3 huruf, dan diakhiri oleh sebuah angka maupun huruf.
Maka, penulisannya adalah:
1
2
3
4
5
6
|
<?php
$string = '2hgd3';
if(preg_match("/^\d[A-Za-z]{3}\w$/", $string)) {
echo 'Pola sesuai';
}
?>
|
11)
Kurung Biasa
Sama seperti dalam matematika, tanda kurung biasa “()” digunakan
untuk mengelompokkan aturan-aturan regex lainnya. Tanda kurung paling dalam
akan diolah terlebih dahulu, setelah itu baru tanda kurung yang diluarnya.
Penggunaannya bisa bermacam-macam, kita bisa melihatnya pada contoh-contoh
selanjutnya.
12)
Karakter Pipe
Karakter pipe atau garis tegak lurus “|” menyatakan operasi
“atau”. Bila digabungkan dengan tanda kurung, kita bisa menentukan dalam string
harus terdapat suatu pola tertentu. Misalkan, format hanya menerima nomer
telepon regional Jakarta, Surabaya, dan Malang, dengan jumlah digit enam atau
tujuh. Maka kita bisa menuliskannya sebagai berikut.
1
2
3
4
5
6
7
8
9
10
11
|
<?php
$string = array('0341-000123', '0311231231',
'021999999', '041321321', '031-12332');
foreach($string as $s) {
if(preg_match("/^(0341|031|021)-?[\d]{6,7}$/",
$s)) {
echo 'Nomer '.$s.' sesuai<br
/>';
} else {
echo 'Nomer '.$s.' tidak sesuai<br
/>';
}
}
?>
|
Hasil regex di atas,
nomer ke-1 sampai dengan ke-3 merupakan pola yang sesuai. Nomer ke-4 tidak
sesuai karena tidak diawali kode area yang ditentukan. Nomer ke-5 tidak sesuai
karena hanya mengandung 5 digit nomer setelah kode area.
13)
Modifiers dan Assertions
Pada contoh sebelumnya, kita telah mempelajari modifier “i”
untuk menyatakan bahwa regex yang digunakan adalah case insensitive. Berikut
ini adalah beberapa modifier lain yang bisa kita gunakan sesuai kasus yang kita
butuhkan.
·
i – tidak menghiraukan
huruf kapital atau case insensitive
·
U – pencarian regex
dengan metode ungreedy
·
s – menyertakan new
line dalam pola
·
m – memperbolehkan
pola dalam baris yang berbeda
·
x – untuk regex dengan
komentar dan whitespace
·
e – evaluasi kode php (khusus
fungsi preg_replace)
·
S – analisis tambahan
terhadap pola
Modifier harus ditulis
setelah delimeter penutup di sebelah kanan regex.
Untuk assertion juga ada beberapa regex yang bisa digunakan.
Karakter “\b” berarti
sebagai word boundary, atau batasan sebuah kata. Ini untuk mencegah pola yang
dicari ada sebagai substring dari kata lainnya. Sebagai contoh, untuk mencari
kata “aman” dalam kalimat “halaman ini telah aman”, maka harus ditulis sebagai
berikut.
1
2
3
4
5
6
|
<?php
$string = 'halaman ini telah aman';
if(preg_match("/\baman\b/", $string)) {
echo 'Pola ditemukan';
}
?>
|
Assertion lainnya adalah:
- \B – bukan karakter word boundary
- \A – awal dari subject
- \Z – akhir dari subject, atau karakter new line
- \z – akhir dari subject
- \G – posisi yang sesuai di awal subject
Semua assertion harus
diawali oleh escape character, untuk menandakan bahwa yang digunakan adalah
assertion.
14)
Delimeter
Pada contoh-contoh sebelumnya, delimeter yang digunakan adalah
tanda slash “/”. Delimeter juga dapat diganti untuk kasus tertentu, terutama
bila kitamemerlukan karakter slash dalam pola yang dicari. Memang bisa
menggunakan escape character, tapi jika cukup banyak tanda slash yang
diperlukan seperti pada pola URL, maka akan cukup merepotkan.
Beberapa
delimeter lain yang bisa digunakan adalah /, @, #, ` (bukan tanda petik), ~, %,
&, tanda petik satu dan dua. Sehingga, kita juga bisa menulisnya seperti
berikut.
1
|
preg_match("#asdf#", $string);
|
15)
Melihat Pola di Depan dan Belakang
Regex memiliki kemampuan untuk mencari pola dengan melihat ke
belakang maupun ke depan dari pola yang dicari. Misalkan, ingin hanya mencari
kata “nama” yang didepannya diikuti oleh tanda titik dua. Atau ingin mencari
kata “media” yang diawali dengan kata “pc”. Semua bisa dilakukan dengan Regex.
Untuk
melihat karakter atau kata di depan kata yang dicari, kita bisa menggunakan
regex “(?=)”. Perhatikan contoh berikut ini.
1
2
3
4
5
6
7
8
|
<?php
$string = 'pcmedia';
if(preg_match("/pc(?=media)/", $string)) {
echo 'Pattern ditemukan';
} else {
echo 'Pattern tidak ditemukan';
}
?>
|
Program tersebut akan
bernilai benar. karena karakter “pc” langsung diikuti oleh “media”. Coba kita ubah
kata tersebut menjadi memiliki spasi, maka akan bernilai salah.
Sedangkan untuk
mencari pattern setelah kata yang dicari, namun menghasilkan nilai negatif,
menggunakan regex “(?!)”. Maksudnya, yang dicari adalah kata yang tidak diikuti
oleh kata lain dalam regex tersebut. Perhatikan contoh berikut ini.
1
2
3
4
5
6
7
8
|
<?php
$string = 'pcmedia';
if(preg_match("/pc(?!media)/", $string)) {
echo 'Pattern ditemukan';
} else {
echo 'Pattern tidak ditemukan';
}
?>
|
Maka yang akan keluar
adalah pernyataan salah. Hal ini karena tidak ada kata “pc” yang tidak diikuti
oleh “media”, sedangkan yang ada yaitu “pcmedia” langsung.
Untuk melihat ke
belakang, regex yang digunakan adalah “(?<=)”. Tujuannya sama, mencari pola
dengan awalan pola lainnya. Contohnya adalah sebagai berikut.
1
2
3
4
5
6
7
8
|
<?php
$string = 'pcmedia';
if(preg_match("/(?<=pc)media/", $string)) {
echo 'Pattern ditemukan';
} else {
echo 'Pattern tidak ditemukan';
}
?>
|
Sedangkan untuk
pencarian ke belakang, namun yang dicari adalah nilai negatifnya, maka
menggunakan regex “(?<!)”. Sehingga yang akan dicari adalah pola karakter
yang tidak diikuti pola yang dimaksud. Coba perhatikan contoh berikut ini.
1
2
3
4
5
6
7
|
<?php
$string = 'pcmedia';
if(preg_match("/(?<!pc)media/", $string)) {
echo 'Pattern ditemukan';
} else {
echo 'Pattern tidak ditemukan';
}
|
Kode di atas tidak
akan menemukan pattern yang dicari, karena dalam string hanya ada kata “media”
yang berawalan “pc”. Harusnya yang dicari oleh pattern tersebut adalah “media”
tanpa berawalan “pc”.
16)
Fungsi Sejenis
Selain preg_match(), ada beberapa fungsi regex yang bisa
langsung Anda gunakan untuk berbagai kasus. Diantaranya adalah sebagai berikut
ini.
·
preg_replace()
Fungsi ini sama dengan
preg_match(), hanya saja fungsi ini akan langsung mengganti pola yang ditemukan
dengan string lain. Fungsi ini menerima minimal 3 parameter, yaitu regex,
string pengganti, dan string yang akan dicari.
1
2
3
4
5
|
<?php
$text = "Kain batik berasal dari negara Malaysia.";
preg_replace("/Malaysia/","Indonesia",$text);
echo $text;
?>
|
·
preg_match_all()
Berbeda dengan
preg_match() yang langsung akan mengembalikan nilai benar jika menemukan satu
saja pattern yang sesuai. Fungsi ini akan mengembalikan jumlah pattern yang
ditemukan, serta dapat mengembalikan apa saja pattern yang ditemukan melalui
parameter ketiga. Karena itu fungsi ini membutuhkan minimal 3 parameter yaitu
regex, string yang akan dicari, serta array yang akan menyimpan semua pola yang
ditemukan
1
2
3
4
5
6
7
8
9
10
11
12
|
<?php
$teks = "Dari awal saya bilang juga ndak apa-apa
".
"mo Perl kek,
PHP kek, Java kek ".
"bahasa-bahasa
laen kek, semua oke!";
$n = 0;
preg_match_all("/((\w+)-.+? )/", $teks,
$matches, PREG_SET_ORDER);
echo "Total = ".count($matches)." kata
ulang, yaitu :<br />";
for ($i=0; $i < count($matches); $i++) {
echo
$matches[$i][1]. "<br />";
$n++;
}
?>
|
17)
Penutup – Pola Email
Setelah mempelajari semua dasar regex dalam PHP, kita bisa
merangkainya menjadi salah satu cara pencarian pola kompleks seperti alamat
email. Ada banyak regex yang bisa diimplementasikan, tergantung cara pikir
masing-masing programmer. Berikut ini adalah salah satu regex yang digunakan
untuk mendeteksi apakah alamat sebuah alamat email valid atau tidak.
1
2
3
4
5
6
7
8
|
<?php
$email = 'me@haqqi.net';
if(preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix",
$email)) {
echo 'Email valid';
} else {
echo 'Email tidak valid';
}
?>
|