Soal 1Apa yang dikembalikan re.match(r"\d+", "abc 123")?
Regular Expressions re — Pencarian dan Penggantian Pola
Pelajari modul re Python dari dasar. Mencakup kapan menggunakan re.match / re.search / re.findall, menggabungkan metacharacter \d / \w / \s / * / + / ?, menangkap grup dengan ( ), substitusi dengan re.sub, dan reuse pola dengan re.compile — dengan latihan praktik yang bisa dijalankan.
Artikel ini membahas modul re untuk regular expressions — "mengekstrak dan mengganti substring yang cocok dengan pola spesifik". Hal-hal yang sering kamu lakukan di proyek nyata — parsing nomor telepon, email, baris log, dan URL — menjadi one-liner.
Tool untuk mencoba regex secara langsung
Regular expressions punya banyak komponen dan sulit dipikirkan murni di kepala. Untuk mengecek apakah pola kamu cocok seperti yang dimaksud, Regex Extractor berjalan sepenuhnya di browser — ketik pola dan teks lalu lihat kecocokan secara real time. Membukanya di samping artikel ini bikin lebih mudah mengikuti.
match, search, dan findall — Tiga fungsi pencarian dan kapan menggunakan masing-masing
Modul re mengekspos beberapa fungsi pencarian, dan kamu memilih di antara tiga tergantung kebutuhan. Namanya deskriptif — match cocok di awal, search mencari satu kecocokan di mana saja, dan findall menemukan semuanya. Rentang pencarian persis, tipe kembalian, dan perilaku saat tidak cocok dirangkum di tabel berikutnya.
| Fungsi | Rentang pencarian | Mengembalikan | Saat tidak cocok |
|---|---|---|---|
| re.match | Hanya awal string | Match object | None |
| re.search | Kecocokan pertama di mana saja | Match object | None |
| re.findall | Semua kecocokan | List string | List kosong [] |
Dari Match object yang dikembalikan re.match dan re.search (objek yang menyimpan posisi match, string yang cocok, dan info grup), kamu membaca string yang cocok dengan memanggil method `.group()`-nya — m.group() atau m.group(0) untuk seluruh match, dan (dengan capture groups yang diperkenalkan nanti) m.group(1) untuk hanya yang ada di dalam tanda kurung. Hanya re.findall mengembalikan list secara langsung, jadi kamu tidak memanggil .group() padanya.
| Metacharacter | Arti | Contoh |
|---|---|---|
| \d | Satu digit (0-9) | \d+ → satu atau lebih digit |
| \w | Satu karakter word (alphanumeric + underscore) | \w+ → ID dan keyword |
| \s | Satu karakter whitespace (spasi / tab / newline) | Pemisah |
| . | Karakter apa pun kecuali newline | Wildcard |
| * | Nol atau lebih dari sebelumnya | a* → kosong juga OK |
| + | Satu atau lebih dari sebelumnya | a+ → minimal satu |
| ? | Nol atau satu dari sebelumnya | Opsional |
| [abc] | Salah satu dari a / b / c | Pilihan |
| ^ / $ | Awal / akhir string | Anchor |
import re
text = "user_id: 12345, age: 30"
# match: dari awal (\w+ adalah deretan karakter word)
m = re.match(r"\w+", text)
print(m.group()) # user_id
# search: deretan digit pertama di mana saja
s = re.search(r"\d+", text)
print(s.group()) # 12345
# findall: setiap deretan digit
nums = re.findall(r"\d+", text)
print(nums) # ['12345', '30']
Tulis regex sebagai raw string r"..."
Backslash muncul di mana-mana di dalam regex. String biasa "\d" bisa membuat escape-nya diinterpretasi oleh layer string sebelum re melihatnya, jadi lebih aman menulis raw string `r"\d"` dengan r di depan. Editor juga cenderung menyorot raw string sebagai regex, yang meningkatkan keterbacaan.
Capture Groups — Menarik bagian spesifik dari pola
Apa pun yang kamu masukkan ke dalam `( )` di dalam regex menjadi capture group — alih-alih hanya seluruh match, kamu bisa menarik setiap potongan secara terpisah. Pola seperti r"#(\d+) on (\d{4})-(\d{2})-(\d{2})" memungkinkanmu memisahkan nomor pesanan dan tanggal dari baris log dalam sekali jalan.
Panggil `.group(N)` pada Match object untuk membaca grup ke-N (dinomori dari 1). .group(0) (atau .group() tanpa argumen) mengembalikan seluruh match.
.group(1) / .group(2). .group(0) adalah seluruh match.import re
text = "Order #1234 placed on 2024-03-15"
# Arti pola:
# # → '#' literal
# (\d+) → satu atau lebih digit → group(1) nomor pesanan
# placed on → 'placed on' literal
# (\d{4}) → 4 digit → group(2) tahun
# (\d{2}) → 2 digit → group(3) bulan
# (\d{2}) → 2 digit → group(4) hari
m = re.search(r"#(\d+) placed on (\d{4})-(\d{2})-(\d{2})", text)
if m:
print("whole:", m.group(0)) # #1234 placed on 2024-03-15
print("order #:", m.group(1)) # 1234
print("year:", m.group(2)) # 2024
print("month:", m.group(3)) # 03
print("day:", m.group(4)) # 15
Memanggil .group() saat Match adalah None melempar error
Ketika re.search tidak menemukan pola, ia mengembalikan None. Memanggil m.group() pada itu crash dengan AttributeError: 'NoneType' object has no attribute 'group'. Selalu cek dengan `if m:` dulu sebelum .group(), atau lakukan keduanya dalam satu langkah dengan operator walrus: if m := re.search(...): ....
re.sub — Mengganti kecocokan pola
"Mask PII dari log", "hapus tag HTML dan simpan teks bodi", "normalkan campuran whitespace full-width dan half-width" — semuanya bermuara pada "tulis ulang apa pun yang cocok dengan pola menjadi sesuatu yang lain". replace string hanya menangani substring tetap, tapi re.sub melakukannya berdasarkan pola.
`re.sub(pola, pengganti, asli)` mengembalikan string baru dengan setiap kecocokan diganti oleh pengganti. String asli tidak berubah (string Python immutable, jadi kamu selalu bekerja dengan nilai kembalian).
import re
# Mask digit di nomor telepon (ganti setiap \d dengan satu *)
text = "Tel: 03-1234-5678"
masked = re.sub(r"\d", "*", text)
print(masked)
# Tel: **-****-****
# Hapus tag HTML untuk hanya menyimpan teks bodi
html = "<p>Halo <b>Dunia</b></p>"
plain = re.sub(r"<[^>]+>", "", html)
print(plain)
# Halo Dunia
re.compile — Reuse pola
Saat kamu menggunakan regex yang sama berulang-ulang, menulis re.search(r"...", text) berkali-kali membuat engine mem-parse (compile) pola setiap kali, yang merupakan pekerjaan sia-sia. `re.compile(pola)` membangun objek pola yang sudah di-compile sekali, dan kamu memanggil method padanya seperti pattern.search(...) / pattern.findall(...) / pattern.sub(...). Kode lebih mudah dibaca dan berjalan lebih cepat.
.search / .findall / .sub sebanyak yang dibutuhkan. Compile saat kamu reuse pola yang sama.import re
# Reuse pola nomor telepon yang sama
phone_re = re.compile(r"\d{2,4}-\d{4}-\d{4}")
print(phone_re.findall("03-1234-5678 atau 080-1111-2222"))
# ['03-1234-5678', '080-1111-2222']
print(phone_re.search("telepon saya 03-9999-0000").group())
# 03-9999-0000
print(phone_re.sub("<phone>", "Kontak: 03-1234-5678"))
# Kontak: <phone>
Cek Pemahaman
Jawab setiap pertanyaan satu per satu.
Soal 2Regex yang benar untuk satu atau lebih digit berturut-turut?
Soal 3Dari re.search(r"(\w+)@(\w+)", "alice@example"), panggilan mana yang mengembalikan hanya domain?
Soal 4Alasan utama untuk menggunakan raw string `r"..."` saat menulis regex di Python?