Jelajahi pencocokan pola JavaScript tingkat lanjut menggunakan ekspresi reguler. Pelajari sintaks regex, aplikasi praktis, dan teknik optimisasi untuk kode yang efisien dan tangguh.
Pencocokan Pola JavaScript dengan Ekspresi Reguler: Panduan Komprehensif
Ekspresi reguler (regex) adalah alat yang sangat kuat untuk pencocokan pola dan manipulasi teks di JavaScript. Mereka memungkinkan pengembang untuk mencari, memvalidasi, dan mengubah string berdasarkan pola yang ditentukan. Panduan ini memberikan gambaran komprehensif tentang ekspresi reguler di JavaScript, mencakup sintaks, penggunaan, dan teknik tingkat lanjut.
Apa itu Ekspresi Reguler?
Ekspresi reguler adalah urutan karakter yang mendefinisikan pola pencarian. Pola-pola ini digunakan untuk mencocokkan dan memanipulasi string. Ekspresi reguler banyak digunakan dalam pemrograman untuk tugas-tugas seperti:
- Validasi Data: Memastikan input pengguna sesuai dengan format tertentu (misalnya, alamat email, nomor telepon).
- Ekstraksi Data: Mengambil informasi spesifik dari teks (misalnya, mengekstrak tanggal, URL, atau harga).
- Cari dan Ganti: Menemukan dan mengganti teks berdasarkan pola yang kompleks.
- Pemrosesan Teks: Memisahkan, menggabungkan, atau mengubah string berdasarkan aturan yang ditentukan.
Membuat Ekspresi Reguler di JavaScript
Di JavaScript, ekspresi reguler dapat dibuat dengan dua cara:
- Menggunakan Literal Ekspresi Reguler: Melampirkan pola di dalam garis miring (
/). - Menggunakan Konstruktor
RegExp: Membuat objekRegExpdengan pola sebagai string.
Contoh:
// Menggunakan literal ekspresi reguler
const regexLiteral = /hello/;
// Menggunakan konstruktor RegExp
const regexConstructor = new RegExp("hello");
Pilihan antara kedua metode tersebut tergantung pada apakah pola tersebut diketahui saat waktu kompilasi atau dibuat secara dinamis. Gunakan notasi literal ketika polanya tetap dan diketahui sebelumnya. Gunakan konstruktor ketika pola perlu dibangun secara terprogram, terutama saat menyertakan variabel.
Sintaks Dasar Regex
Ekspresi reguler terdiri dari karakter yang merepresentasikan pola yang akan dicocokkan. Berikut adalah beberapa komponen fundamental regex:
- Karakter Literal: Mencocokkan karakter itu sendiri (misalnya,
/a/mencocokkan karakter 'a'). - Metakarakter: Memiliki arti khusus (misalnya,
.,^,$,*,+,?,[],{},(),\,|). - Kelas Karakter: Merepresentasikan himpunan karakter (misalnya,
[abc]mencocokkan 'a', 'b', atau 'c'). - Kuantifier: Menentukan berapa kali sebuah karakter atau grup harus muncul (misalnya,
*,+,?,{n},{n,},{n,m}). - Jangkar (Anchors): Mencocokkan posisi dalam string (misalnya,
^mencocokkan awal,$mencocokkan akhir).
Metakarakter Umum:
.(titik): Mencocokkan karakter tunggal apa pun kecuali baris baru.^(caret): Mencocokkan awal dari string.$(dolar): Mencocokkan akhir dari string.*(asterisk): Mencocokkan nol atau lebih kemunculan dari karakter atau grup sebelumnya.+(plus): Mencocokkan satu atau lebih kemunculan dari karakter atau grup sebelumnya.?(tanda tanya): Mencocokkan nol atau satu kemunculan dari karakter atau grup sebelumnya. Digunakan untuk karakter opsional.[](kurung siku): Mendefinisikan kelas karakter, mencocokkan satu karakter apa pun di dalam kurung.{}(kurung kurawal): Menentukan jumlah kemunculan yang akan dicocokkan.{n}mencocokkan tepat n kali,{n,}mencocokkan n atau lebih kali,{n,m}mencocokkan antara n dan m kali.()(kurung biasa): Mengelompokkan karakter bersama-sama dan menangkap substring yang cocok.\(backslash): Meloloskan metakarakter, memungkinkan Anda untuk mencocokkannya secara harfiah.|(pipa): Bertindak sebagai operator "atau", mencocokkan ekspresi sebelum atau sesudahnya.
Kelas Karakter:
[abc]: Mencocokkan salah satu dari karakter a, b, atau c.[^abc]: Mencocokkan karakter apa pun yang *bukan* a, b, atau c.[a-z]: Mencocokkan huruf kecil apa pun dari a hingga z.[A-Z]: Mencocokkan huruf besar apa pun dari A hingga Z.[0-9]: Mencocokkan digit apa pun dari 0 hingga 9.[a-zA-Z0-9]: Mencocokkan karakter alfanumerik apa pun.\d: Mencocokkan digit apa pun (setara dengan[0-9]).\D: Mencocokkan karakter non-digit apa pun (setara dengan[^0-9]).\w: Mencocokkan karakter kata apa pun (alfanumerik plus garis bawah; setara dengan[a-zA-Z0-9_]).\W: Mencocokkan karakter non-kata apa pun (setara dengan[^a-zA-Z0-9_]).\s: Mencocokkan karakter spasi putih apa pun (spasi, tab, baris baru, dll.).\S: Mencocokkan karakter non-spasi putih apa pun.
Kuantifier:
*: Mencocokkan elemen sebelumnya nol atau lebih kali. Contohnya,a*mencocokkan "", "a", "aa", "aaa", dan seterusnya.+: Mencocokkan elemen sebelumnya satu atau lebih kali. Contohnya,a+mencocokkan "a", "aa", "aaa", tetapi tidak "".?: Mencocokkan elemen sebelumnya nol atau satu kali. Contohnya,a?mencocokkan "" atau "a".{n}: Mencocokkan elemen sebelumnya tepat *n* kali. Contohnya,a{3}mencocokkan "aaa".{n,}: Mencocokkan elemen sebelumnya *n* atau lebih kali. Contohnya,a{2,}mencocokkan "aa", "aaa", "aaaa", dan seterusnya.{n,m}: Mencocokkan elemen sebelumnya antara *n* dan *m* kali (inklusif). Contohnya,a{2,4}mencocokkan "aa", "aaa", atau "aaaa".
Jangkar (Anchors):
^: Mencocokkan awal dari string. Contohnya,^Hellomencocokkan string yang *dimulai* dengan "Hello".$: Mencocokkan akhir dari string. Contohnya,World$mencocokkan string yang *berakhir* dengan "World".\b: Mencocokkan batas kata. Ini adalah posisi antara karakter kata (\w) dan karakter non-kata (\W) atau awal atau akhir string. Contohnya,\bword\bmencocokkan seluruh kata "word".
Flag:
Flag regex memodifikasi perilaku ekspresi reguler. Flag ditambahkan ke akhir literal regex atau dilewatkan sebagai argumen kedua ke konstruktor RegExp.
g(global): Mencocokkan semua kemunculan pola, bukan hanya yang pertama.i(ignore case): Melakukan pencocokan tanpa mempedulikan huruf besar/kecil.m(multiline): Mengaktifkan mode multiline, di mana^dan$mencocokkan awal dan akhir setiap baris (dipisahkan oleh\n).s(dotAll): Memungkinkan titik (.) untuk mencocokkan karakter baris baru juga.u(unicode): Mengaktifkan dukungan Unicode penuh.y(sticky): Hanya mencocokkan dari indeks yang ditunjukkan oleh propertilastIndexdari regex.
Metode Regex JavaScript
JavaScript menyediakan beberapa metode untuk bekerja dengan ekspresi reguler:
test(): Menguji apakah sebuah string cocok dengan pola. Mengembalikantrueataufalse.exec(): Menjalankan pencarian untuk kecocokan dalam sebuah string. Mengembalikan sebuah array yang berisi teks yang cocok dan grup yang ditangkap, ataunulljika tidak ada kecocokan yang ditemukan.match(): Mengembalikan sebuah array yang berisi hasil pencocokan string terhadap ekspresi reguler. Berperilaku berbeda dengan dan tanpa flagg.search(): Menguji kecocokan dalam sebuah string. Mengembalikan indeks kecocokan pertama, atau -1 jika tidak ada kecocokan yang ditemukan.replace(): Mengganti kemunculan pola dengan string pengganti atau fungsi yang mengembalikan string pengganti.split(): Membagi sebuah string menjadi array substring berdasarkan ekspresi reguler.
Contoh Penggunaan Metode Regex:
// test()
const regex = /hello/;
const str = "hello world";
console.log(regex.test(str)); // Output: true
// exec()
const regex2 = /hello (\w+)/;
const str2 = "hello world";
const result = regex2.exec(str2);
console.log(result); // Output: ["hello world", "world", index: 0, input: "hello world", groups: undefined]
// match() dengan flag 'g'
const regex3 = /\d+/g; // Mencocokkan satu atau lebih digit secara global
const str3 = "Ada 123 apel dan 456 jeruk.";
const matches = str3.match(regex3);
console.log(matches); // Output: ["123", "456"]
// match() tanpa flag 'g'
const regex4 = /\d+/;
const str4 = "Ada 123 apel dan 456 jeruk.";
const match = str4.match(regex4);
console.log(match); // Output: ["123", index: 4, input: "Ada 123 apel dan 456 jeruk.", groups: undefined]
// search()
const regex5 = /world/;
const str5 = "hello world";
console.log(str5.search(regex5)); // Output: 6
// replace()
const regex6 = /world/;
const str6 = "hello world";
const newStr = str6.replace(regex6, "JavaScript");
console.log(newStr); // Output: hello JavaScript
// replace() dengan sebuah fungsi
const regex7 = /(\d+)-(\d+)-(\d+)/;
const str7 = "Tanggal hari ini adalah 2023-10-27";
const newStr2 = str7.replace(regex7, (match, year, month, day) => {
return `${day}/${month}/${year}`;
});
console.log(newStr2); // Output: Tanggal hari ini adalah 27/10/2023
// split()
const regex8 = /, /;
const str8 = "apel, pisang, ceri";
const arr = str8.split(regex8);
console.log(arr); // Output: ["apel", "pisang", "ceri"]
Teknik Regex Tingkat Lanjut
Grup Penangkapan (Capturing Groups):
Kurung biasa () digunakan untuk membuat grup penangkapan dalam ekspresi reguler. Grup yang ditangkap memungkinkan Anda untuk mengekstrak bagian spesifik dari teks yang cocok. Metode exec() dan match() mengembalikan sebuah array di mana elemen pertama adalah seluruh kecocokan, dan elemen-elemen berikutnya adalah grup yang ditangkap.
const regex = /(\d{4})-(\d{2})-(\d{2})/;
const dateString = "2023-10-27";
const match = regex.exec(dateString);
console.log(match[0]); // Output: 2023-10-27 (Seluruh kecocokan)
console.log(match[1]); // Output: 2023 (Grup tangkapan pertama - tahun)
console.log(match[2]); // Output: 10 (Grup tangkapan kedua - bulan)
console.log(match[3]); // Output: 27 (Grup tangkapan ketiga - hari)
Grup Penangkapan Bernama:
ES2018 memperkenalkan grup penangkapan bernama, yang memungkinkan Anda memberikan nama ke grup penangkapan menggunakan sintaks (?. Ini membuat kode lebih mudah dibaca dan dipelihara.
const regex = /(?\d{4})-(?\d{2})-(?\d{2})/;
const dateString = "2023-10-27";
const match = regex.exec(dateString);
console.log(match.groups.year); // Output: 2023
console.log(match.groups.month); // Output: 10
console.log(match.groups.day); // Output: 27
Grup Non-Penangkapan:
Jika Anda perlu mengelompokkan bagian dari regex tanpa menangkapnya (misalnya, untuk menerapkan kuantifier ke sebuah grup), Anda dapat menggunakan grup non-penangkapan dengan sintaks (?:...). Ini menghindari alokasi memori yang tidak perlu untuk grup yang ditangkap.
const regex = /(?:https?:\/\/)?([\w\.]+)/; // Mencocokkan URL tetapi hanya menangkap nama domain
const url = "https://www.example.com/path";
const match = regex.exec(url);
console.log(match[1]); // Output: www.example.com
Lookarounds:
Lookaround adalah asersi lebar-nol yang mencocokkan posisi dalam sebuah string berdasarkan pola yang mendahului (lookbehind) atau mengikuti (lookahead) posisi tersebut, tanpa menyertakan pola lookaround itu sendiri dalam kecocokan.
- Positive Lookahead:
(?=...)Mencocokkan jika pola di dalam lookahead *mengikuti* posisi saat ini. - Negative Lookahead:
(?!...)Mencocokkan jika pola di dalam lookahead *tidak* mengikuti posisi saat ini. - Positive Lookbehind:
(?<=...)Mencocokkan jika pola di dalam lookbehind *mendahului* posisi saat ini. - Negative Lookbehind:
(? Mencocokkan jika pola di dalam lookbehind *tidak* mendahului posisi saat ini.
Contoh:
// Positive Lookahead: Dapatkan harga hanya jika diikuti oleh USD
const regex = /\d+(?= USD)/;
const text = "Harganya adalah 100 USD";
const match = text.match(regex);
console.log(match); // Output: ["100"]
// Negative Lookahead: Dapatkan kata hanya jika tidak diikuti oleh angka
const regex2 = /\b\w+\b(?! \d)/;
const text2 = "apel 123 pisang jeruk 456";
const matches = text2.match(regex2);
console.log(matches); // Output: null karena match() hanya mengembalikan kecocokan pertama tanpa flag 'g', yang bukan yang kita butuhkan.
// untuk memperbaikinya:
const regex3 = /\b\w+\b(?! \d)/g;
const text3 = "apel 123 pisang jeruk 456";
const matches3 = text3.match(regex3);
console.log(matches3); // Output: [ 'pisang' ]
// Positive Lookbehind: Dapatkan nilai hanya jika didahului oleh $
const regex4 = /(?<=\$)\d+/;
const text4 = "Harganya adalah $200";
const match4 = text4.match(regex4);
console.log(match4); // Output: ["200"]
// Negative Lookbehind: Dapatkan kata hanya jika tidak didahului oleh kata 'tidak'
const regex5 = /(?
Referensi Mundur (Backreferences):
Referensi mundur memungkinkan Anda untuk merujuk ke grup yang ditangkap sebelumnya dalam ekspresi reguler yang sama. Mereka menggunakan sintaks \1, \2, dll., di mana nomornya sesuai dengan nomor grup yang ditangkap.
const regex = /([a-z]+) \1/;
const text = "hello hello dunia";
const match = regex.exec(text);
console.log(match); // Output: ["hello hello", "hello", index: 0, input: "hello hello dunia", groups: undefined]
Aplikasi Praktis Ekspresi Reguler
Memvalidasi Alamat Email:
Kasus penggunaan umum untuk ekspresi reguler adalah memvalidasi alamat email. Meskipun regex validasi email yang sempurna sangat kompleks, berikut adalah contoh yang disederhanakan:
const emailRegex = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/;
console.log(emailRegex.test("test@example.com")); // Output: true
console.log(emailRegex.test("invalid-email")); // Output: false
console.log(emailRegex.test("test@sub.example.co.uk")); // Output: true
Mengekstrak URL dari Teks:
Anda dapat menggunakan ekspresi reguler untuk mengekstrak URL dari blok teks:
const urlRegex = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g;
const text = "Kunjungi situs web kami di https://www.example.com atau lihat http://blog.example.org.";
const urls = text.match(urlRegex);
console.log(urls); // Output: ["https://www.example.com", "http://blog.example.org"]
Mengurai Data CSV:
Ekspresi reguler dapat digunakan untuk mengurai data CSV (Comma-Separated Values). Berikut adalah contoh memisahkan string CSV menjadi array nilai, menangani field yang dikutip:
const csvString = 'John,Doe,"123, Main St",New York';
const csvRegex = /(?:"([^"]*(?:""[^"]*)*)")|([^,]+)/g; //Regex CSV yang diperbaiki
let values = [];
let match;
while (match = csvRegex.exec(csvString)) {
values.push(match[1] ? match[1].replace(/""/g, '"') : match[2]);
}
console.log(values); // Output: ["John", "Doe", "123, Main St", "New York"]
Validasi Nomor Telepon Internasional
Memvalidasi nomor telepon internasional itu rumit karena format dan panjangnya yang bervariasi. Solusi yang kuat seringkali melibatkan penggunaan pustaka, tetapi regex yang disederhanakan dapat memberikan validasi dasar:
const phoneRegex = /^\+(?:[0-9] ?){6,14}[0-9]$/;
console.log(phoneRegex.test("+1 555 123 4567")); // Output: true (Contoh AS)
console.log(phoneRegex.test("+44 20 7946 0500")); // Output: true (Contoh Inggris)
console.log(phoneRegex.test("+81 3 3224 5000")); // Output: true (Contoh Jepang)
console.log(phoneRegex.test("123-456-7890")); // Output: false
Validasi Kekuatan Kata Sandi
Ekspresi reguler berguna untuk menegakkan kebijakan kekuatan kata sandi. Contoh di bawah ini memeriksa panjang minimum, huruf besar, huruf kecil, dan angka.
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/;
console.log(passwordRegex.test("P@ssword123")); // Output: true
console.log(passwordRegex.test("password")); // Output: false (tidak ada huruf besar atau angka)
console.log(passwordRegex.test("Password")); // Output: false (tidak ada angka)
console.log(passwordRegex.test("Pass123")); // Output: false (tidak ada huruf kecil)
console.log(passwordRegex.test("P@ss1")); // Output: false (kurang dari 8 karakter)
Teknik Optimisasi Regex
Ekspresi reguler bisa jadi mahal secara komputasi, terutama untuk pola yang kompleks atau input yang besar. Berikut beberapa teknik untuk mengoptimalkan kinerja regex:
- Jadilah Spesifik: Hindari menggunakan pola yang terlalu umum yang mungkin cocok lebih dari yang dimaksud.
- Gunakan Jangkar (Anchors): Kaitkan regex ke awal atau akhir string jika memungkinkan (
^,$). - Hindari Penelusuran Mundur (Backtracking): Minimalkan backtracking dengan menggunakan kuantifier posesif (misalnya,
++bukan+) atau grup atomik ((?>...)) jika sesuai. - Kompilasi Sekali: Jika Anda menggunakan regex yang sama beberapa kali, kompilasi sekali dan gunakan kembali objek
RegExp. - Gunakan Kelas Karakter dengan Bijak: Kelas karakter (
[]) umumnya lebih cepat daripada alternasi (|). - Buat Tetap Sederhana: Hindari regex yang terlalu kompleks yang sulit dipahami dan dipelihara. Terkadang, memecah tugas yang kompleks menjadi beberapa regex yang lebih sederhana atau menggunakan teknik manipulasi string lain bisa lebih efisien.
Kesalahan Umum Regex
- Lupa Meloloskan Metakarakter: Gagal meloloskan karakter khusus seperti
.,*,+,?,$,^,(,),[,],{,},|, dan\saat Anda ingin mencocokkannya secara harfiah. - Terlalu Sering Menggunakan
.(titik): Titik mencocokkan karakter apa pun (kecuali baris baru dalam beberapa mode), yang dapat menyebabkan kecocokan tak terduga jika tidak digunakan dengan hati-hati. Jadilah lebih spesifik bila memungkinkan dengan menggunakan kelas karakter atau pola lain yang lebih ketat. - Ketamakan (Greediness): Secara default, kuantifier seperti
*dan+bersifat serakah dan akan mencocokkan sebanyak mungkin. Gunakan kuantifier malas (*?,+?) saat Anda perlu mencocokkan string sesingkat mungkin. - Penggunaan Jangkar yang Salah: Kesalahpahaman tentang perilaku
^(awal string/baris) dan$(akhir string/baris) dapat menyebabkan pencocokan yang salah. Ingatlah untuk menggunakan flagm(multiline) saat bekerja dengan string multiline dan ingin^dan$mencocokkan awal dan akhir setiap baris. - Tidak Menangani Kasus Tepi: Gagal mempertimbangkan semua skenario input yang mungkin dan kasus tepi dapat menyebabkan bug. Uji regex Anda secara menyeluruh dengan berbagai input, termasuk string kosong, karakter tidak valid, dan kondisi batas.
- Masalah Kinerja: Membuat regex yang terlalu kompleks dan tidak efisien dapat menyebabkan masalah kinerja, terutama dengan input besar. Optimalkan regex Anda dengan menggunakan pola yang lebih spesifik, menghindari backtracking yang tidak perlu, dan mengkompilasi regex yang digunakan berulang kali.
- Mengabaikan Pengkodean Karakter: Tidak menangani pengkodean karakter dengan benar (terutama Unicode) dapat menyebabkan hasil yang tidak terduga. Gunakan flag
usaat bekerja dengan karakter Unicode untuk memastikan pencocokan yang benar.
Kesimpulan
Ekspresi reguler adalah alat yang berharga untuk pencocokan pola dan manipulasi teks di JavaScript. Menguasai sintaks dan teknik regex memungkinkan Anda untuk secara efisien menyelesaikan berbagai masalah, dari validasi data hingga pemrosesan teks yang kompleks. Dengan memahami konsep yang dibahas dalam panduan ini dan berlatih dengan contoh-contoh dunia nyata, Anda dapat menjadi mahir dalam menggunakan ekspresi reguler untuk meningkatkan keterampilan pengembangan JavaScript Anda.
Ingatlah bahwa ekspresi reguler bisa jadi kompleks, dan seringkali sangat membantu untuk mengujinya secara menyeluruh menggunakan penguji regex online seperti regex101.com atau regexr.com. Ini memungkinkan Anda untuk memvisualisasikan kecocokan dan men-debug masalah apa pun secara efektif. Selamat membuat kode!