Quantifiers — Regex

Apa itu Quantifier? Quantifier menentukan berapa kali karakter atau grup sebelumnya harus muncul agar cocok. Tanpa quantifier, setiap elemen regex cocok tepat…

Apa itu Quantifier?

Quantifier menentukan berapa kali karakter atau grup sebelumnya harus muncul agar cocok. Tanpa quantifier, setiap elemen regex cocok tepat satu kali.

Quantifier Dasar

Quantifier Arti Contoh
* 0 atau lebih ab*c cocok "ac", "abc", "abbc"
+ 1 atau lebih ab+c cocok "abc", "abbc" (bukan "ac")
? 0 atau 1 (opsional) colou?r cocok "color", "colour"
{n} Tepat n kali a{3} cocok "aaa"
{n,} Minimal n kali a{2,} cocok "aa", "aaa", "aaaa"...
{n,m} Antara n dan m kali a{2,4} cocok "aa", "aaa", "aaaa"

Contoh Penggunaan

// * (nol atau lebih)
/go*gle/.test("ggle");    // true (0 huruf "o")
/go*gle/.test("google");  // true (2 huruf "o")
/go*gle/.test("gooogle"); // true (3 huruf "o")

// + (satu atau lebih)
/go+gle/.test("ggle");    // false (butuh minimal 1 "o")
/go+gle/.test("google");  // true

// ? (opsional)
/https?:/.test("http:");   // true
/https?:/.test("https:");  // true

// {n} (tepat n kali)
/\d{4}/.test("2024");  // true
/\d{4}/.test("123");   // false (hanya 3 digit)

// {n,m} (range)
/\d{2,4}/.test("1");     // false
/\d{2,4}/.test("12");    // true
/\d{2,4}/.test("12345"); // true (cocok "1234" di awal)

Greedy vs Lazy

Secara default, quantifier bersifat greedy — mereka mencocokkan sebanyak mungkin karakter. Tambahkan ? setelah quantifier untuk membuatnya lazy (mencocokkan sesedikit mungkin).

const html = "<b>tebal</b> dan <i>miring</i>";

// Greedy: .* mengambil sebanyak mungkin
html.match(/<.+>/);   // ["<b>tebal</b> dan <i>miring</i>"]

// Lazy: .+? mengambil sesedikit mungkin
html.match(/<.+?>/);  // ["<b>"]

// Semua tag dengan lazy + global
html.match(/<.+?>/g); // ["<b>", "</b>", "<i>", "</i>"]

Ini sangat penting saat parsing HTML atau teks yang punya delimiter berulang!

Quantifier pada Character Class dan Grup

Quantifier berlaku untuk elemen tepat di depannya:

// Quantifier pada karakter tunggal
/ab+/;      // "a" diikuti 1+ huruf "b"

// Quantifier pada character class
/[0-9]+/;   // 1+ digit berturut-turut

// Quantifier pada group
/(ha)+/;    // 1+ pengulangan "ha"

"hahaha".match(/(ha)+/);  // ["hahaha"]

Contoh Praktis

// Validasi nomor telepon Indonesia (08xx-xxxx-xxxx)
const phoneRegex = /^08\d{2}-?\d{4}-?\d{4}$/;
console.log(phoneRegex.test("0812-3456-7890")); // true
console.log(phoneRegex.test("081234567890"));   // true

// Cari kata yang panjangnya 5-8 huruf
const kata = "aku suka belajar programming dan coding";
console.log(kata.match(/\b[a-zA-Z]{5,8}\b/g));
// ["belajar", "coding"]

// Parsing angka dengan optional desimal
const angkaRegex = /\d+\.?\d*/g;
console.log("harga 99.9 dan 100".match(angkaRegex));
// ["99.9", "100"]

🎭 Analogi sehari-hari: Quantifier = aturan jumlah cabang. * = "minimal 0 cabang OK" (boleh kosong). + = "minimal 1 cabang wajib". ? = "0 atau 1 cabang, opsional". {2,5} = "antara 2 sampai 5 cabang". Greedy = pohon ambil cabang sebanyak mungkin. Lazy = pohon ambil cabang sesedikit mungkin.

💡 Greedy vs Lazy critical untuk parsing: Default greedy = <.+> di <b>tebal</b> ambil semua dari <b> sampai </b> (gak match per tag). Lazy <.+?> ambil sesedikit mungkin = match per tag. Untuk parse delimited content (HTML tag, string quotes), lazy hampir selalu yang dibutuhkan.

⚠️ Jebakan klasik:

🎯 Pattern umum:

TL;DR: Quantifier = berapa kali repeat. * (0+), + (1+), ? (0/1), {n,m} (range). Default greedy ambil maksimal — pakai ? jadikan lazy untuk parse delimited content. Awas catastrophic backtracking dengan nested quantifier.