Regex Identifier #

Artikel ini adalah referensi lengkap semua identifier — simbol, metacharacter, dan konstruksi sintaksis — yang bisa digunakan dalam regular expression di TypeScript. Berbeda dari artikel Regex sebelumnya yang membahas cara menggunakan regex dan metode-metodenya, artikel ini berfokus pada kamus elemen-elemen penyusun pola regex itu sendiri: apa artinya setiap simbol, bagaimana mereka berinteraksi, dan jebakan apa yang perlu diwaspadai. Jadikan artikel ini sebagai rujukan saat membangun atau membaca pola regex yang kompleks.

Karakter Literal #

Karakter literal adalah karakter yang cocok dengan dirinya sendiri secara tepat. Mayoritas karakter alfanumerik adalah literal:

// Huruf dan angka adalah literal — cocok dengan dirinya sendiri
/abc/.test("abc");     // true — cocok persis
/abc/.test("ABC");     // false — case-sensitive by default
/abc/.test("xabcx");  // true — ditemukan di dalam string

// PERHATIAN: Beberapa karakter punya makna khusus (metacharacter)
// dan harus di-escape dengan \ untuk diperlakukan sebagai literal
// . * + ? ^ $ { } [ ] | ( ) \
/a\.b/.test("a.b");  // true — titik literal
/a\.b/.test("axb");  // false — titik literal hanya cocok dengan "."

Karakter yang Perlu Di-escape #

// Metacharacter yang harus di-escape untuk diperlakukan sebagai literal
const periksaTitikEscaped = /example\.com/;   // Titik literal
const periksaBintang = /a\*b/;                 // Bintang literal
const periksaKurung = /\(ok\)/;                // Tanda kurung literal
const periksaSlash = /https:\/\//;             // Forward slash dalam literal

// Tabel metacharacter yang perlu di-escape:
// .  ->  \.     titik
// *  ->  \*     bintang
// +  ->  \+     plus
// ?  ->  \?     tanda tanya
// ^  ->  \^     caret (di luar kelas karakter)
// $  ->  \$     dollar
// {  ->  \{     kurung kurawal buka
// }  ->  \}     kurung kurawal tutup
// [  ->  \[     kurung siku buka
// ]  ->  \]     kurung siku tutup
// |  ->  \|     pipe
// (  ->  \(     kurung biasa buka
// )  ->  \)     kurung biasa tutup
// \  ->  \\     backslash

// Helper: escape semua metacharacter dalam string dinamis
function escapeRegex(teks: string): string {
  return teks.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

const inputPengguna = "harga: 100.000 (diskon)";
const polaAman = new RegExp(escapeRegex(inputPengguna));
polaAman.test("total harga: 100.000 (diskon) ya"); // true

Metakarakter #

Metakarakter adalah karakter yang memiliki makna khusus dalam pola regex — bukan mencocokkan dirinya sendiri, melainkan mendeskripsikan posisi atau tipe karakter:

. — Titik (Any Character) #

// Titik cocok dengan SATU karakter apapun kecuali newline (\n)
/a.b/.test("acb");  // true  — 'c' cocok dengan titik
/a.b/.test("a b");  // true  — spasi cocok dengan titik
/a.b/.test("a\nb"); // false — newline tidak cocok dengan titik (kecuali flag s)
/a.b/.test("ab");   // false — harus ada tepat satu karakter di antara a dan b

// Dengan flag s (dotAll) — titik cocok dengan newline juga
/a.b/s.test("a\nb"); // true — flag s mengaktifkan dotAll mode

// ANTI-PATTERN: Titik sering digunakan terlalu lebar
// /.*/ cocok dengan string apapun termasuk yang tidak diinginkan
// Lebih baik gunakan kelas karakter yang spesifik jika memungkinkan

^ — Caret (Awal String/Baris) #

// ^ di luar kelas karakter = anchor awal string
/^halo/.test("halo dunia");  // true  — dimulai dengan "halo"
/^halo/.test("hai, halo");   // false — "halo" bukan di awal

// Dengan flag m (multiline) — ^ cocok di awal setiap baris
const teksMultibaris = "baris satu\nbaris dua\nbaris tiga";
teksMultibaris.match(/^baris/gm);
// ["baris", "baris", "baris"] — cocok di awal setiap baris

// ^ DI DALAM kelas karakter = negasi (lihat bagian Character Classes)
/[^abc]/.test("d"); // true — 'd' bukan a, b, atau c

$ — Dollar (Akhir String/Baris) #

// $ = anchor akhir string
/dunia$/.test("halo dunia");    // true  — diakhiri dengan "dunia"
/dunia$/.test("dunia baru");    // false — "dunia" bukan di akhir

// Dengan flag m — $ cocok di akhir setiap baris
const teks = "baris satu\nbaris dua";
teks.match(/\w+$/gm);
// ["satu", "dua"] — kata terakhir di setiap baris

// Validasi format lengkap — gunakan ^ dan $ bersamaan
/^\d{5}$/.test("12345"); // true  — tepat 5 digit, tidak lebih tidak kurang
/^\d{5}$/.test("123456"); // false — 6 digit
/^\d{5}$/.test("1234");  // false — 4 digit

\b dan \B — Word Boundary #

// \b = batas kata — posisi antara \w dan \W (atau awal/akhir string)
/\bkata\b/.test("ini kata");      // true  — "kata" berdiri sendiri
/\bkata\b/.test("katakata");      // false — tidak ada batas kata
/\bkata\b/.test("kata-kata");     // true  — tanda hubung adalah \W
/\bkan\b/.test("akan");           // false — "kan" bagian dari "akan"

// \B = bukan batas kata
/\Bkan\B/.test("seakan");         // true  — "kan" di tengah kata
/\Bkan\B/.test("kan");            // false — "kan" berdiri sendiri

// Kasus penggunaan umum: mencari kata utuh
const teks = "TypeScript tidak sama dengan JavaScript";
teks.match(/\bScript\b/g);   // null — "Script" bukan kata utuh
teks.match(/\bTypeScript\b/g); // ["TypeScript"] — kata utuh

Kelas Karakter (Character Classes) #

Kelas karakter [...] mencocokkan satu karakter dari kumpulan yang didefinisikan:

// [abc] — cocok dengan a, b, atau c
/[aeiou]/.test("hello");  // true  — 'e' dan 'o' adalah vokal
/[aeiou]/.test("rhythm"); // false — tidak ada vokal

// [a-z] — rentang: cocok dengan huruf kecil a sampai z
/[a-z]/.test("Hello");  // true  — 'e', 'l', 'l', 'o' dalam rentang
/[A-Z]/.test("hello");  // false — semua huruf kecil
/[0-9]/.test("abc");    // false — tidak ada digit
/[0-9]/.test("abc5");   // true  — '5' dalam rentang

// Kombinasi rentang
/[a-zA-Z0-9]/.test("Hello123"); // true — alfanumerik

// [^...] — negasi: cocok dengan karakter yang TIDAK ada dalam kelas
/[^aeiou]/.test("rhythm"); // true  — semua karakter bukan vokal
/[^0-9]/.test("abc");      // true  — tidak ada digit
/[^0-9]/.test("123");      // false — semua digit

Kelas Karakter Khusus dalam [...] #

// Di dalam [], beberapa karakter kehilangan makna khususnya
// . tidak perlu di-escape di dalam []
/[.]/.test(".");  // true  — titik literal di dalam []
/[.]/.test("a");  // false — hanya cocok dengan titik literal

// - harus di posisi pertama, terakhir, atau di-escape untuk menjadi literal
/[-+]/.test("-"); // true  — minus di posisi pertama = literal
/[+\-]/.test("-"); // true  — minus di-escape = literal

// ^ hanya memiliki makna negasi di posisi pertama
/[a^b]/.test("^"); // true  — ^ di tengah = literal
/[^ab]/.test("c");  // true  — ^ di awal = negasi

Predefined Character Classes #

Kelas karakter yang sudah didefinisikan sebelumnya sebagai shorthand:

// \d — digit, setara dengan [0-9]
/\d/.test("5");   // true
/\d/.test("a");   // false

// \D — bukan digit, setara dengan [^0-9]
/\D/.test("a");   // true
/\D/.test("5");   // false

// \w — word character, setara dengan [a-zA-Z0-9_]
/\w/.test("a");   // true
/\w/.test("_");   // true
/\w/.test("@");   // false
// PERHATIAN: \w tidak cocok dengan karakter non-ASCII seperti "é", "ñ", "ا"

// \W — bukan word character
/\W/.test("@");   // true
/\W/.test("a");   // false

// \s — whitespace: spasi, tab (\t), newline (\n), carriage return (\r), form feed (\f)
/\s/.test(" ");   // true  — spasi
/\s/.test("\t");  // true  — tab
/\s/.test("\n");  // true  — newline
/\s/.test("a");   // false

// \S — bukan whitespace
/\S/.test("a");   // true
/\S/.test(" ");   // false

Tabel Predefined Character Classes #

IdentifierArtiSetara Dengan
\dDigit[0-9]
\DBukan digit[^0-9]
\wWord character[a-zA-Z0-9_]
\WBukan word character[^a-zA-Z0-9_]
\sWhitespace[ \t\n\r\f\v]
\SBukan whitespace[^ \t\n\r\f\v]
.Karakter apapun (kecuali \n)[^\n]
\nNewline
\tTab
\rCarriage return

Unicode Property Escapes (Flag u) #

Dengan flag u, TypeScript/JavaScript mendukung pencocokan berdasarkan properti Unicode — sangat berguna untuk teks multibahasa:

// \p{properti} — cocok karakter dengan properti Unicode tertentu
// Memerlukan flag u

/\p{L}/u.test("A");   // true  — huruf (Letter)
/\p{L}/u.test("1");   // false — bukan huruf
/\p{L}/u.test("ا");   // true  — huruf Arab
/\p{L}/u.test("你");  // true  — karakter Cina

/\p{N}/u.test("5");   // true  — angka (Number)
/\p{P}/u.test(".");   // true  — tanda baca (Punctuation)

/\p{Script=Arabic}/u.test("ا");   // true  — karakter Arab
/\p{Script=Latin}/u.test("A");    // true  — karakter Latin
/\p{Script=Han}/u.test("你");     // true  — karakter Han (Cina/Jepang/Korea)

/\p{Emoji}/u.test("😊");          // true  — emoji
/\p{Emoji}/u.test("A");           // false

// \P{} = negasi dari \p{}
/\P{L}/u.test("1");  // true  — bukan huruf

Quantifier — Mengontrol Pengulangan #

Quantifier menentukan berapa kali elemen sebelumnya harus muncul:

Quantifier Dasar #

// * — 0 atau lebih (greedy)
/ab*c/.test("ac");    // true  — 0 'b'
/ab*c/.test("abc");   // true  — 1 'b'
/ab*c/.test("abbbc"); // true  — 3 'b'

// + — 1 atau lebih (greedy)
/ab+c/.test("ac");    // false — harus ada minimal 1 'b'
/ab+c/.test("abc");   // true  — 1 'b'
/ab+c/.test("abbbc"); // true  — 3 'b'

// ? — 0 atau 1 (opsional, greedy)
/colou?r/.test("color");  // true  — tanpa 'u'
/colou?r/.test("colour"); // true  — dengan 'u'

// {n} — tepat n kali
/\d{4}/.test("2025");  // true
/\d{4}/.test("202");   // false — kurang dari 4

// {n,} — minimal n kali
/\d{3,}/.test("123");    // true
/\d{3,}/.test("12");     // false

// {n,m} — antara n sampai m kali (inklusif)
/\d{2,4}/.test("12");    // true  — 2 digit
/\d{2,4}/.test("1234");  // true  — 4 digit
/\d{2,4}/.test("12345"); // true  — cocok 4 digit di awal
/\d{2,4}/.test("1");     // false — 1 digit

Greedy vs Lazy vs Possessive #

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

// Greedy — ambil sebanyak mungkin (default)
html.match(/<.+>/)?.[0];     // "<b>tebal</b> dan <i>miring</i>"

// Lazy — ambil sesedikit mungkin (tambahkan ? setelah quantifier)
html.match(/<.+?>/)?.[0];    // "<b>"

// Tabel: Greedy → Lazy
// *   →  *?     (0 atau lebih, lazy)
// +   →  +?     (1 atau lebih, lazy)
// ?   →  ??     (0 atau 1, lazy)
// {n,m} → {n,m}? (rentang, lazy)

// Contoh nyata: ekstrak semua tag HTML
const semuaTag = html.match(/<.+?>/g);
// ["<b>", "</b>", "<i>", "</i>"]

// vs greedy yang hanya mengambil dari < pertama ke > terakhir
const greedy = html.match(/<.+>/g);
// ["<b>tebal</b> dan <i>miring</i>"]

Grouping dan Capturing #

(...) — Capturing Group #

// Capturing group menangkap bagian yang cocok untuk diakses kembali
const tanggal = /(\d{4})-(\d{2})-(\d{2})/.exec("2025-05-07");
if (tanggal) {
  console.log(tanggal[0]); // "2025-05-07" — kecocokan penuh
  console.log(tanggal[1]); // "2025" — grup 1
  console.log(tanggal[2]); // "05"   — grup 2
  console.log(tanggal[3]); // "07"   — grup 3
}

// Backreference dalam pola — \1 merujuk ke isi grup 1
// Berguna untuk mencari pengulangan kata
/(\b\w+\b) \1/.test("halo halo"); // true  — kata diulang
/(\b\w+\b) \1/.test("halo dunia"); // false — kata berbeda

// Backreference dalam replace — $1, $2, dst
"2025-05-07".replace(/(\d{4})-(\d{2})-(\d{2})/, "$3/$2/$1");
// "07/05/2025"

(?:...) — Non-capturing Group #

// Non-capturing group — kelompokkan tanpa tangkap indeks
// Berguna untuk grouping alternation atau quantifier tanpa overhead

// Tanpa non-capturing: "ab" ditangkap sebagai grup
/(ab)+/.exec("ababab")?.[1]; // "ab" — hanya tangkapan TERAKHIR

// Dengan non-capturing: tidak ada tangkapan, lebih efisien
/(?:ab)+/.exec("ababab")?.[1]; // undefined — tidak ada grup

// Kasus umum: kelompokkan alternation
/(?:https?|ftp):\/\//.test("https://example.com"); // true
/(?:https?|ftp):\/\//.test("ftp://files.com");     // true

(?<nama>...) — Named Capturing Group #

// Named group — akses lewat .groups.nama bukan indeks
const formatISO = /(?<tahun>\d{4})-(?<bulan>\d{2})-(?<hari>\d{2})/;
const hasilISO = formatISO.exec("tanggal: 2025-05-07");

if (hasilISO?.groups) {
  const { tahun, bulan, hari } = hasilISO.groups;
  // tahun: string, bulan: string, hari: string
  console.log(`${hari} ${['','Jan','Feb','Mar','Apr','Mei','Jun','Jul','Agu','Sep','Okt','Nov','Des'][parseInt(bulan)]} ${tahun}`);
  // "07 Mei 2025"
}

// Named backreference — \k<nama>
/(?<kata>\b\w+\b) \k<kata>/.test("halo halo"); // true — kata diulang

Alternation #

// | — OR: cocok dengan salah satu dari pola yang dipisahkan
/kucing|anjing/.test("saya punya kucing"); // true
/kucing|anjing/.test("saya punya anjing"); // true
/kucing|anjing/.test("saya punya ikan");   // false

// Alternation dalam group — membatasi scope |
/^(senin|selasa|rabu|kamis|jumat)$/.test("senin");   // true
/^(senin|selasa|rabu|kamis|jumat)$/.test("sabtu");   // false
/^(senin|selasa|rabu|kamis|jumat)$/.test("senin  "); // false — ada spasi

// Alternation mencoba dari kiri ke kanan — urutan penting!
// "ab" vs "a" — "ab" harus di kiri agar bisa cocok dulu
/ab|a/.exec("ab")?.[0];  // "ab" — "ab" dicoba dulu
/a|ab/.exec("ab")?.[0];  // "a"  — "a" cocok duluan!

Assertions #

Assertions cocok dengan posisi dalam string, bukan karakter:

// ^ dan $ sudah dibahas di Metakarakter di atas

// \b — word boundary
/\bTypeScript\b/.test("TypeScript itu keren"); // true
/\bScript\b/.test("TypeScript");               // false — bagian dari kata

// \B — non-word boundary (kebalikan \b)
/\Btype\B/.test("prototype");  // true  — "type" di tengah kata
/\Btype\B/.test("type");       // false — "type" berdiri sendiri

// Zero-width: assertions tidak mengonsumsi karakter
// Ini berarti cocok pada POSISI, bukan karakter
const hasil = "abc".match(/(?=b)/);
// Cocok di posisi sebelum 'b', tapi tidak mengonsumsi 'b'

Lookahead dan Lookbehind (Lengkap) #

Lookaround adalah zero-width assertion yang memeriksa konteks tanpa termasuk dalam hasil:

// =============================================
// LOOKAHEAD
// =============================================

// (?=pola) — Positive Lookahead: cocok jika diikuti pola
"100px 200em 300px".match(/\d+(?=px)/g);
// ["100", "300"] — angka yang diikuti "px"

// (?!pola) — Negative Lookahead: cocok jika TIDAK diikuti pola
"100px 200em 300px".match(/\d+(?!px)(?!\d)/g);
// ["200"] — angka yang tidak diikuti "px"

// =============================================
// LOOKBEHIND
// =============================================

// (?<=pola) — Positive Lookbehind: cocok jika didahului pola
"$100 €200 £300".match(/(?<=\$)\d+/g);
// ["100"] — angka yang didahului "$"

// (?<!pola) — Negative Lookbehind: cocok jika TIDAK didahului pola
"$100 €200 £300".match(/(?<!\$)\d+/g);
// ["200", "300"] — angka yang tidak didahului "$"
// (abaikan fakta bahwa ini bisa lebih komplex di implementasi nyata)

// =============================================
// KOMBINASI LOOKAROUND
// =============================================

// Ekstrak nilai di antara tag tertentu
const xml = "<nama>Budi Santoso</nama>";
xml.match(/(?<=<nama>).+?(?=<\/nama>)/)?.[0];
// "Budi Santoso" — tanpa tag

// Validasi password dengan lookahead:
// min 8 karakter, minimal 1 huruf besar, 1 huruf kecil, 1 angka
const regexPassword = /^(?=.*[A-Z])(?=.*[a-z])(?=.*\d).{8,}$/;
regexPassword.test("Password1");  // true
regexPassword.test("password1");  // false — tidak ada huruf besar
regexPassword.test("PASSWORD1");  // false — tidak ada huruf kecil
regexPassword.test("Pass1");      // false — kurang dari 8 karakter

Tabel Referensi Cepat Semua Identifier #

KARAKTER LITERAL
  abc         — Huruf/angka literal
  \.          — Titik literal (escape metacharacter)

METAKARAKTER
  .           — Karakter apapun kecuali \n (atau semua dengan flag s)
  ^           — Awal string (atau awal baris dengan flag m)
  $           — Akhir string (atau akhir baris dengan flag m)
  \b          — Word boundary
  \B          — Non-word boundary

KELAS KARAKTER
  [abc]       — Salah satu: a, b, atau c
  [^abc]      — Bukan a, b, atau c
  [a-z]       — Rentang huruf kecil
  [A-Z]       — Rentang huruf besar
  [0-9]       — Rentang digit
  [a-zA-Z0-9] — Gabungan rentang

PREDEFINED CLASSES
  \d          — Digit [0-9]
  \D          — Bukan digit [^0-9]
  \w          — Word char [a-zA-Z0-9_]
  \W          — Bukan word char
  \s          — Whitespace
  \S          — Bukan whitespace
  \p{L}       — Letter Unicode (flag u)
  \p{N}       — Number Unicode (flag u)
  \p{Emoji}   — Emoji (flag u)

QUANTIFIER (GREEDY)
  *           — 0 atau lebih
  +           — 1 atau lebih
  ?           — 0 atau 1
  {n}         — Tepat n kali
  {n,}        — Minimal n kali
  {n,m}       — Antara n dan m kali

QUANTIFIER (LAZY — tambah ?)
  *?          — 0 atau lebih (lazy)
  +?          — 1 atau lebih (lazy)
  ??          — 0 atau 1 (lazy)
  {n,m}?      — Antara n dan m (lazy)

GROUPING
  (pola)      — Capturing group
  (?:pola)    — Non-capturing group
  (?<nama>)   — Named capturing group
  (a|b)       — Alternation dalam group

BACKREFERENCE
  \1 \2 ...   — Backreference by index
  \k<nama>    — Backreference by name
  $1 $2 ...   — Dalam replace (by index)
  $<nama>     — Dalam replace (by name)

LOOKAROUND
  (?=pola)    — Positive lookahead
  (?!pola)    — Negative lookahead
  (?<=pola)   — Positive lookbehind
  (?<!pola)   — Negative lookbehind

ESCAPE SEQUENCES
  \n          — Newline
  \t          — Tab
  \r          — Carriage return
  \0          — Null character
  \uXXXX      — Unicode character (hex)
  \u{XXXXX}   — Unicode codepoint (flag u)

Ringkasan #

  • Escape metacharacter dengan \ saat ingin mencocokkan mereka sebagai literal — karakter . * + ? ^ $ { } [ ] | ( ) \ semuanya punya makna khusus.
  • Gunakan fungsi escapeRegex() saat membangun pola dari input pengguna atau data dinamis untuk mencegah karakter metacharacter tidak sengaja mengubah perilaku pola.
  • [...] cocok dengan satu karakter — bukan urutan karakter; [abc] cocok dengan ‘a’ atau ‘b’ atau ‘c’, bukan dengan string “abc”.
  • ^ di dalam [^...] adalah negasi, bukan anchor — [^abc] artinya “karakter apapun selain a, b, c”.
  • \w tidak mendukung karakter non-ASCII — huruf Arab, aksara Jawa, atau karakter berdiakritik tidak cocok dengan \w; gunakan \p{L} dengan flag u untuk pencocokan multibahasa yang benar.
  • Greedy adalah default — quantifier +, *, ?, {n,m} mengambil sebanyak mungkin; tambahkan ? setelahnya (+?, *?) untuk lazy yang mengambil sesedikit mungkin.
  • Named capturing group (?<nama>pola) jauh lebih mudah dibaca daripada indeks angka — gunakan untuk pola dengan lebih dari dua grup.
  • Lookaround adalah zero-width — mereka memeriksa konteks di sekitar posisi tanpa mengonsumsi karakter, sehingga tidak muncul dalam hasil kecocokan.
  • Urutan alternation penting| mencoba dari kiri ke kanan dan berhenti saat pertama cocok; letakkan pola yang lebih panjang/spesifik di kiri agar tidak tergeser oleh pola yang lebih pendek.

← Sebelumnya: Regex   Berikutnya: TS Config →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact