Regex di Bahasa Lain (PHP, Python, Go)
Sejauh ini kita belajar regex dari sudut pandang JavaScript. Tapi setiap bahasa punya flavor regex yang sedikit berbeda — flag-nya beda, syntax delimiter beda, dan fitur lanjutan kadang tidak tersedia. Mari bedah perbedaannya.
Flavor Regex
| Flavor | Dipakai di | Catatan |
|---|---|---|
| ECMAScript | JavaScript | Default di browser + Node |
| PCRE | PHP, Perl, kebanyakan bahasa | Paling lengkap fitur |
| POSIX BRE/ERE | grep, sed tradisional | Lebih terbatas |
| RE2 | Go regexp, Google |
Linear time, tidak ada backreferences/lookbehind |
PHP: preg_* Functions
PHP pakai PCRE dengan delimiter di sekeliling pattern:
// Delimiter `/` (paling umum), bisa juga # atau ~
if (preg_match("/^\d{4}-\d{2}-\d{2}$/", "2024-03-15")) {
echo "Format valid";
}
// preg_match_all: semua match
preg_match_all("/\d+/", "Ada 3 dan 12 ikan", $matches);
// $matches[0] = ["3", "12"]
// preg_replace: substitusi
$hasil = preg_replace("/\s+/", " ", "terlalu banyak spasi");
// "terlalu banyak spasi"
// preg_replace_callback: dengan fungsi
$upper = preg_replace_callback("/[a-z]+/", fn($m) => strtoupper($m[0]), "halo dunia");
// "HALO DUNIA"
Flag PHP (setelah delimiter): i (case-insensitive), m (multiline), s (dotall), u (Unicode), x (verbose, boleh whitespace dan komentar).
Python: re Module
Python punya re.match vs re.search — perbedaannya penting:
import re
# re.match: anchored di awal string (seperti regex dengan ^)
re.match(r"hello", "hello world") # Match
re.match(r"world", "hello world") # None!
# re.search: cari di mana saja
re.search(r"world", "hello world") # Match
# re.findall: semua match sebagai list
re.findall(r"\d+", "Ada 3 dan 12 ikan")
# ["3", "12"]
# re.sub: substitusi
re.sub(r"\s+", " ", "terlalu banyak spasi")
# Compiled regex (lebih cepat kalau dipakai berulang)
pattern = re.compile(r"\d{4}-\d{2}-\d{2}")
pattern.match("2024-03-15")
Flag Python: re.I/re.IGNORECASE, re.M/re.MULTILINE, re.S/re.DOTALL, re.X/re.VERBOSE, re.U/re.UNICODE (default di Python 3).
Go: regexp (RE2)
Go pakai RE2 — dijamin linear time, jadi tidak bisa kena ReDoS. Trade-off: tidak support backreferences \1 dan lookbehind (?<=...).
import "regexp"
re := regexp.MustCompile(`\d+`)
re.MatchString("Ada 3 ikan") // true
re.FindString("Ada 3 ikan") // "3"
re.FindAllString("3 dan 12", -1) // ["3", "12"]
re.ReplaceAllString("3 dan 12", "X") // "X dan X"
Raw Strings: Hindari Double-Escape Neraka
PHP, JavaScript, dan Python sama-sama butuh escape backslash di string biasa. Solusi:
| Bahasa | Raw string syntax |
|---|---|
| Python | r"\d+" |
| Go | `\d+` |
| JavaScript | /\d+/ (regex literal) atau String.raw |
| PHP | Single quotes '\d+' (tapi masih perlu \\ untuk backslash literal) |
Perbedaan Penting
| Fitur | JS | PHP | Python | Go (RE2) |
|---|---|---|---|---|
Backreferences \1 |
✅ | ✅ | ✅ | ❌ |
Lookbehind (?<=...) |
✅ (modern) | ✅ | ✅ | ❌ |
Named groups (?<name>...) |
✅ | ✅ ((?P<name>...) juga) |
✅ ((?P<name>...)) |
✅ ((?P<name>...)) |
Possessive a++ |
❌ | ✅ | ❌ | ❌ |
Atomic (?>...) |
❌ | ✅ | ✅ (3.11+) | ❌ |
Unicode \p{Letter} |
✅ (flag u) |
✅ (flag u) |
✅ | ✅ |
grep vs egrep vs grep -P
# Basic regex (BRE): `+`, `?`, `(` harus di-escape
grep "colou\?r" file.txt
# Extended regex (ERE): syntax modern tanpa escape
grep -E "colou?r" file.txt
egrep "colou?r" file.txt # Sama dengan grep -E
# PCRE mode: full PCRE features
grep -P "\d{4}-\d{2}-\d{2}" file.txt
Tips Berpindah Bahasa
- Cek delimiter — PHP butuh
/, JS pakai/juga tapi sebagai literal, Python string. - Cek default anchor — Python
re.matchanchored, kebanyakan yang lain tidak. - Cek flag syntax — konstanta
re.Ivs characteri. - Cek fitur support — kalau pindah ke Go/RE2, pastikan tidak pakai backref/lookbehind.
- Test di regex101.com — pilih flavor yang sesuai target bahasa.
🎭 Analogi sehari-hari: Regex flavor = dialect bahasa. Indonesia, Malaysia, Brunei semua "Melayu" tapi beda kata, beda intonasi, beda slang. JavaScript, PHP, Python, Go semua "regex" tapi beda syntax, beda fitur, beda quirk. Kalimat di satu dialect bisa lucu/salah di dialect lain.
💡 RE2 (Go) tradeoff: Linear time guaranteed (no ReDoS!) tapi gak support backreferences (\1) dan lookbehind. Worth it untuk safety. Cloudflare seharusnya pakai RE2 di 2019 — outage gak akan terjadi. Ada trend industri ke RE2 untuk user-facing regex.
⚠️ Jebakan cross-language:
- Python
re.matchanchored di awal — beda dari kebanyakan bahasa. Pakaire.searchuntuk match anywhere - PHP delimiter wajib (
/pattern/notpattern) - Go RE2 reject backref/lookbehind tapi flag
(?P<name>)for named (POSIX-style) - POSIX BRE (grep tradisional) gak support
+,?,{}tanpa escape:\+,\?,\{ - Java backslash double:
"\\d"=\ddi pattern (string escape + regex escape)
🎯 Quick reference dialect:
- JS:
/pattern/flagsliteral,match(),replace(), ECMAScript flavor - PHP:
preg_match("/pattern/flags", str)PCRE flavor - Python:
re.search(r"pattern", str, re.I)flag konstanta - Go:
regexp.MustCompile(\pattern`)` RE2, no backref/lookbehind - Java:
Pattern.compile("pattern").matcher(str)PCRE-ish, double-escape
TL;DR: Regex flavor (ECMAScript, PCRE, POSIX, RE2) beda fitur + syntax. Pindah bahasa: cek delimiter, default anchor, flag syntax, fitur support. RE2 trade speed untuk linear-time guarantee — pakai untuk user input.