Mengetahui sebuah teks cocok dengan pola sering kali belum cukup; kita biasanya ingin mengambil bagiannya: nama pengguna dari alamat email, tanggal dari baris log, atau jumlah dari kalimat pesanan. Capture group adalah mekanisme regex untuk menandai bagian pola sehingga potongan teks yang cocok dengan bagian tersebut bisa diambil terpisah. Chapter ini membahas capture group bernomor, group bernama, group tanpa capturing, sampai backreference.
Capture Groups dan Method group() #
Tanda kurung (...) mengelompokkan sebagian pola sekaligus menangkap teks yang cocok dengannya. Setiap pasang kurung mendapat nomor urut mulai dari 1, dihitung dari kurung buka paling kiri.
import re
hasil = re.search(r"(\w+)@(\w+)\.com", "Kontak resmi: [email protected]")
print(hasil.group(0))
print(hasil.group(1))
print(hasil.group(2))
print(hasil.groups())Output yang Dihasilkan:
[email protected]
budi
example
('budi', 'example')Method group(0) selalu berisi kecocokan utuh; group(1) dan group(2) berisi isi masing-masing tanda kurung; groups() mengembalikan seluruh isi group sebagai satu tuple — siap di-unpack ke variabel.
Memecah Baris Log Menjadi Data #
Kasus nyata: satu baris log berisi tanggal, waktu, level, dan pesan yang bercampur dalam satu string. Pola dengan delapan capture group memecahnya sekaligus:
import re
log = "2025-06-15 09:30:00 INFO pesanan 4821 dibuat oleh budi"
pola = r"(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2}) (\w+) (.+)"
hasil = re.search(pola, log)
tahun, bulan, tanggal, jam, menit, detik, level, pesan = hasil.groups()
print(f"{tanggal}/{bulan}/{tahun} {jam}:{menit}:{detik} [{level}] {pesan}")Output yang Dihasilkan:
15/06/2025 09:30:00 [INFO] pesanan 4821 dibuat oleh budiMari kita telaah apa yang terjadi pada baris-baris kode di atas:
- Baris 3 (
log = "2025-06-15 09:30:00 INFO pesanan 4821 dibuat oleh budi"): satu baris log disimpan sebagai string; setiap bagian berpola — tanggal, waktu, level, sisa pesan — akan dibungkus tanda kurungnya sendiri di baris berikutnya, sementara spasi, tanda hubung, dan tanda titik dua di luar kurung berperan sebagai pemisah literal. - Baris 6 (
hasil = re.search(pola, log)): fungsire.search()memindailogdari kiri lalu membungkus kecocokan pertama ke dalam objectre.Match. - Baris 7 (
tahun, bulan, tanggal, jam, menit, detik, level, pesan = hasil.groups()): isi kedelapan group di-unpack ke delapan variabel dalam satu pernyataan penugasan. - Baris 8 (
print(f"{tanggal}/{bulan}/{tahun} {jam}:{menit}:{detik} [{level}] {pesan}")): potongan-potongan tersebut dirangkai ulang menjadi format tanggal Indonesia.
Perhatikan group terakhir (.+): berkat perilaku greedy yang kita pelajari pada Chapter Character Classes dan Quantifiers, group tersebut melahap sisa baris termasuk spasinya — tepat yang dibutuhkan kolom pesan.
Named Groups #
Nomor urut cepat menjadi beban mental saat pola memanjang dan group berpindah posisi saat pola direvisi. Named group (?P<nama>...) memberi label pada group sehingga group bisa dipanggil berdasarkan nama:
import re
pola = r"(?P<tahun>\d{4})-(?P<bulan>\d{2})-(?P<tanggal>\d{2})"
hasil = re.search(pola, "Laporan akhir tahun 2025-06-15 telah final.")
print(hasil.group("tahun"))
print(hasil.group("tanggal"))
print(hasil.groupdict())Output yang Dihasilkan:
2025
15
{'tahun': '2025', 'bulan': '06', 'tanggal': '15'}Method groupdict() mengembalikan dictionary dari seluruh named group — bentuk yang siap diteruskan ke function lain sebagai keyword argument. Label (?P<...>) juga memaksa kita menamakan maksud setiap bagian pola, sehingga pola ikut terdokumentasi.
Group Tanpa Capturing #
Kadang tanda kurung dibutuhkan hanya untuk mengelompokkan — misalnya memilih antara beberapa alternatif dengan | — tanpa ingin menangkap isinya. Awalan ?: membentuk non-capturing group:
import re
belanja = "beras 5 kg, gula 2 kg, tepung 500 gram"
print(re.findall(r"\d+ (?:kg|gram)", belanja))Output yang Dihasilkan:
['5 kg', '2 kg', '500 gram']Tanpa pengelompokan, pola \d+ kg|gram terbaca sebagai “\d+ kg atau gram” — bukan maksud kita. Awalan ?: menjaga pengelompokan tetap utuh tanpa memakan nomor group. Manfaat lainnya: begitu pola memuat capture group, re.findall() berubah perilaku dan hanya mengembalikan isi group — detail yang kita bedah pada Chapter Searching dan Matching.
Backreference #
Backreference \1 sampai \9 merujuk pada isi group yang telah ditangkap di dalam pola yang sama: mesin mencocokkan ulang teks yang persis sama dengan hasil tangkapan group. Kegunaan klasiknya adalah mendeteksi kata yang tidak sengaja terketik dua kali:
import re
teks = "Siti memesan kopi kopi dua kali, lalu teh sekali."
print(re.findall(r"(\w+) \1", teks))Output yang Dihasilkan:
['kopi']Pola (\w+) \1 berbunyi: tangkap satu kata, cocokkan satu spasi, lalu tuntut kata yang sama muncul lagi. Kata kopi yang terketik ganda ketahuan, sementara pasangan kata lain seperti lalu teh tidak dipermasalahkan karena kedua katanya berbeda.