Anchor, group, dan alternasi

Pola terstruktur dengan anchor, grup penangkap, dan alternasi beserta pengambilan potongannya.

Daftar isi

Pola yang baik tidak berhenti pada menemukan teks, tetapi juga menyatakan bentuk teks secara terstruktur. Topik ini menambahkan tiga alat penyusun di atas literal dan kelas karakter, yaitu anchor untuk mengunci posisi kecocokan, capturing group (grup penangkap) untuk menyimpan potongan kecocokan, dan alternation (alternasi) untuk memilih di antara beberapa bentuk. Hasil akhirnya adalah satu pola terstruktur yang memilah baris log menjadi kepala log dan pasangan kunci-nilai yang siap diproses.

Anchor: mengunci posisi kecocokan#

Anchor menancapkan kecocokan pada posisi tertentu tanpa memakan karakter teks. Tanda ^ menuntut kecocokan di awal string, tanda $ menuntut kecocokan di akhir string, dan \b menuntut batas antara karakter kata dengan karakter bukan kata. Karena tidak memakan karakter apa pun, anchor sering disebut kecocokan berlebar nol (zero-width match).

Batas kata \b paling sering dipakai untuk mencari kata utuh. Pola \bsuhu\b mencocokkan kata suhu di mana pun posisinya, tetapi menolak potongan suhu di dalam suhunya. Tanpa batas kata, pencarian menjadi jauh lebih berisik karena potongan di tengah kata ikut ditemukan.

python Contoh: anchor ^, $, dan 
import re

teks = "Pukul 09.14, suhu udara 27 derajat, suhu tanah 24 derajat, suhunya naik."

# anchor ^ : kecocokan harus berada di awal string
print(re.findall(r"^suhu", teks))
print(re.findall(r"^suhu", "suhu tanah juga dicatat"))

# anchor $ : kecocokan harus berada di akhir string
print(re.findall(r"naik\.$", teks))

# anchor \b : batas antara karakter kata dan bukan kata
print(re.findall(r"\bsuhu\b", teks))
text Keluaran
[]
['suhu']
['naik.']
['suhu', 'suhu']

Keluaran memperlihatkan ketiga peran sekaligus. Pada teks pertama, pola ^suhu menghasilkan daftar kosong karena baris tidak diawali kata tersebut, sedangkan pada teks kedua kecocokannya ditemukan. Pola naik\.$ hanya berhasil bila titik penutup berada tepat di akhir string. Pencarian \bsuhu\b menemukan dua kata utuh dan meloloskan suhunya karena batas kata tidak terpenuhi di antara u dan n.

Grup penangkap dan grup non-penangkap#

Pasangan kurung (...) membentuk grup penangkap, yaitu bagian pola yang kecocokannya disimpan untuk diambil kembali. Grup dinomori dari kiri ke kanan mulai dari 1, sedangkan group(0) selalu berisi kecocokan utuh. Kurung yang bersarang ikut dinomori, yaitu grup bagian dalam memperoleh nomor berikutnya sesuai urutan kurung pembukanya. Ketika pola tidak memuat grup sama sekali, findall mengembalikan kecocokan utuh sebagai string. Cara paling ringkas membaca seluruh potongan adalah groups(), yang mengembalikan tuple berisi semua grup sekaligus.

Non-capturing group (grup non-penangkap) ditulis (?:...). Bentuk ini tetap mengelompokkan elemen untuk keperluan kuantifier atau alternasi, tetapi tidak menyimpan potongan dan tidak menggeser nomor grup lain. Grup non-penangkap lazim dipakai agar keluaran findall tetap bersih dan nomor grup tidak berubah ketika pola disunting.

python Contoh: grup penangkap dan grup non-penangkap
import re

log = "2026-11-07 09:14:22 [sensor-03] suhu=27.5C"

# grup penangkap: setiap pasangan kurung menyimpan potongannya sendiri
m = re.search(r"(\d{4})-(\d{2})-(\d{2})", log)
print(m.group(0))
print(m.groups())

# grup non-penangkap: mengelompokkan tanpa menambah nomor grup
print(re.findall(r"(\d{2}):(\d{2}):(\d{2})", log))
print(re.findall(r"(?:\d{2}:){2}(\d{2})", log))
text Keluaran
2026-11-07
('2026', '11', '07')
[('09', '14', '22')]
['22']

Dua baris terakhir membandingkan keduanya secara langsung. Pola (\d{2}):(\d{2}):(\d{2}) mengembalikan tuple tiga grup, sedangkan (?:\d{2}:){2}(\d{2}) mengulang bentuk dua digit berikut titik dua sebanyak dua kali tanpa penangkapan, lalu hanya menyimpan detiknya. Keduanya mencocokkan rentang yang sama, tetapi jumlah potongan yang tersimpan berbeda.

Grup bernama#

Named group (grup bernama) ditulis (?P<nama>...) dan menyimpan kecocokan di bawah nama yang dipilih sendiri. Pengambilannya memakai group("nama"), sedangkan groupdict() mengembalikan seluruh pasangan nama dan nilai sekaligus sebagai dictionary. Nama membuat pola dan kode pembacanya tetap mudah diurai ketika jumlah grup bertambah, karena rujukan tidak bergantung pada nomor urut.

Nama yang diperbolehkan adalah pengenal Python yang sah, sehingga huruf dan angka boleh dipakai tetapi tanda hubung tidak, dan dua grup tidak boleh berbagi nama yang sama dalam satu pola. Sejak Python 3.6, objek Match juga menerima penulisan kurung siku seperti m["nilai"], sehingga pembacaan grup bernama menjadi lebih singkat.

python Contoh: named group pada baris status
import re

baris = "status=OK"

# named group: grup dengan nama yang mudah dirujuk
m = re.search(r"status=(?P<nilai>\w+)", baris)
print(m.group("nilai"), "|", m.groupdict())
text Keluaran
OK | {'nilai': 'OK'}

Pola di atas menangkap nilai status dan menyerahkannya dua kali, pertama melalui nama nilai, kemudian sebagai dictionary utuh. Untuk pola dengan empat grup atau lebih, nama jauh lebih tahan terhadap penyuntingan dibandingkan nomor urut. Keluaran groupdict() juga siap diteruskan ke kode lain tanpa pembongkaran manual.

Alternasi#

Alternation (alternasi) ditulis dengan tanda | dan mencocokkan salah satu pilihan polanya. Mesin menguji pilihan dari kiri ke kanan pada setiap posisi, dan pilihan pertama yang berhasil langsung dipakai. Urutan pilihan menentukan hasil terutama ketika satu pilihan merupakan awalan dari pilihan lainnya.

Karena | memiliki prioritas (precedence) paling rendah, pilihan yang lebih panjang sebaiknya ditulis lebih dahulu, atau kedua ujungnya dijepit batas kata. Alternasi juga sering diletakkan di dalam grup agar terikat rapi dengan elemen di sekitarnya. Sebagai contoh, (?:OK|GAGAL) membatasi efek alternasi pada satu kelompok kecil, sedangkan OK|GAGAL telanjang akan membagi pola menjadi dua cabang yang jauh lebih lebar. Pola jam pada diagram studi kasus memakai bentuk bergrup itu agar sisa pola tetap berada di luar pilihan.

python Contoh: urutan pilihan pada alternasi
import re

# alternasi menguji pilihan dari kiri ke kanan pada setiap posisi
print(re.findall(r"catatan|catat", "catatan harian"))
print(re.findall(r"catat|catatan", "catatan harian"))

# batas kata membuat hasil tidak lagi bergantung pada urutan
print(re.findall(r"\b(?:catatan|catat)\b", "catatan harian"))
text Keluaran
['catatan']
['catat']
['catatan']

Baris pertama mengembalikan catatan karena pilihan itu diuji lebih dahulu dan berhasil. Baris kedua mengembalikan catat karena pilihan pendek berhasil pada posisi yang sama sebelum pilihan panjang sempat dicoba. Baris ketiga menambahkan \b di kedua ujung grup non-penangkap sehingga kata utuh selalu yang dikembalikan, tidak lagi bergantung pada urutan penulisan pilihan.

Studi kasus: pola terstruktur untuk baris log#

Anchor, grup bernama, dan alternasi kini dapat digabungkan menjadi satu pola yang menyatakan bentuk baris log secara utuh. Diagram berikut menandai setiap komponen pola jam dan status catatan sensor, mulai dari anchor pembuka hingga anchor penutup, beserta kelas, kuantifier, literal, dan alternasi yang menyusun bagian tengahnya.

^(?P<jam>\d{2}:\d{2}) (?P<status>OK|GAGAL)$anchor, yaitu tanda ^ dan $ yang mengunci posisigrup bernama (?P<nama>...)kelas karakter \d dengan kuantifier {2}literal, yaitu titik dua dan spasialternasi OK|GAGAL
Anatomi pola terstruktur pada baris catatan sensor

Berkas ekstrak_log.py menerapkan pola terstruktur serupa pada tiga baris log. Grup bernama tanggal, jam, dan sensor menangkap kepala log, sedangkan grup isi menampung sisa baris untuk dipilah menjadi pasangan kunci-nilai. Pemilahan memakai findall, dan daftar pasangannya diurutkan dengan sorted agar keluaran stabil.

python ekstrak_log.py
import re

# Pola terstruktur untuk baris log sensor: anchor, grup bernama, dan isi.
pola = re.compile(
    r"^(?P<tanggal>\d{4}-\d{2}-\d{2}) (?P<jam>\d{2}:\d{2}:\d{2}) "
    r"\[(?P<sensor>sensor-\d+)\] (?P<isi>.+)$"
)

log = (
    "2026-11-07 09:14:22 [sensor-03] suhu=27.5 kelembapan=68 status=OK",
    "2026-11-07 09:15:22 [sensor-03] suhu=27.9 kelembapan=69 status=OK",
    "2026-11-07 09:16:22 [sensor-01] suhu=25.4 kelembapan=71 status=GAGAL",
)

for baris in log:
    m = pola.search(baris)
    pasangan = dict(re.findall(r"(\w+)=(\S+)", m.group("isi")))
    print(m.group("tanggal"), m.group("jam"), m.group("sensor"), sorted(pasangan.items()))

# Seluruh grup bernama dapat diambil sekaligus sebagai satu dict.
print(pola.search(log[0]).groupdict())
text Keluaran
2026-11-07 09:14:22 sensor-03 [('kelembapan', '68'), ('status', 'OK'), ('suhu', '27.5')]
2026-11-07 09:15:22 sensor-03 [('kelembapan', '69'), ('status', 'OK'), ('suhu', '27.9')]
2026-11-07 09:16:22 sensor-01 [('kelembapan', '71'), ('status', 'GAGAL'), ('suhu', '25.4')]
{'tanggal': '2026-11-07', 'jam': '09:14:22', 'sensor': 'sensor-03', 'isi': 'suhu=27.5 kelembapan=68 status=OK'}

Keluaran menunjukkan tiga hal sekaligus. Anchor ^ dan $ memastikan pola mencakup seluruh baris, sehingga baris yang bentuknya menyimpang akan gagal cocok dan mudah diketahui. Grup bernama menyerahkan setiap bagian kepala log dengan namanya, dan groupdict() mengembalikan semuanya sebagai dictionary yang siap diteruskan ke tabel atau basis data. Perintah berikut menjalankan berkas dari terminal.

bash
# jalankan program ekstraksi dari folder tempat berkas disimpan
python3 ekstrak_log.py
text Keluaran
2026-11-07 09:14:22 sensor-03 [('kelembapan', '68'), ('status', 'OK'), ('suhu', '27.5')]
2026-11-07 09:15:22 sensor-03 [('kelembapan', '69'), ('status', 'OK'), ('suhu', '27.9')]
2026-11-07 09:16:22 sensor-01 [('kelembapan', '71'), ('status', 'GAGAL'), ('suhu', '25.4')]
{'tanggal': '2026-11-07', 'jam': '09:14:22', 'sensor': 'sensor-03', 'isi': 'suhu=27.5 kelembapan=68 status=OK'}

Kesalahan umum#

Kurung siku literal yang tidak ditulis \[. Tanda [ pada teks seperti [sensor-03] membentuk kelas karakter apabila ditulis telanjang dalam pola, sehingga [sensor-03] justru berarti satu karakter dari kumpulan s, e, n, o, r, tanda hubung, 0, atau 3. Kecocokan yang diharapkan satu baris penuh berubah menjadi satu karakter, dan pencarian gagal tanpa pesan error. Tulis kurung siku literal dengan \[ dan \].

Nomor grup yang bergeser. Kode yang membaca group(2) rusak begitu satu grup baru disisipkan di depannya, karena penomoran bergeser ke kanan dan potongan yang terbaca berpindah. Untuk pola yang kerap disunting, gunakan grup bernama agar rujukan tidak bergantung pada urutan, atau pakai grup non-penangkap untuk pengelompokan yang potongannya tidak diperlukan.

Mengira $ menolak baris baru di akhir string. Menurut aturan modul re, tanda $ juga cocok tepat sebelum satu baris baru di ujung string, sehingga pola naik\.$ masih berhasil pada teks suhunya naik.\n. Apabila akhir string harus mutlak, gunakan \Z yang hanya menancap di posisi paling akhir. Perbedaan ini jarang terlihat pada data yang sudah dipangkas, tetapi muncul begitu baris log membawa karakter baris baru.

Ringkasan#

  • Anchor ^, $, dan \b menancapkan kecocokan tanpa memakan karakter, sehingga posisi dan keutuhan kata dapat dituntut secara eksplisit.
  • Grup penangkap menyimpan potongan kecocokan per nomor, grup non-penangkap (?:...) mengelompokkan tanpa menyimpan, dan grup bernama (?P<nama>...) memberi label yang mudah dirujuk.
  • Alternasi | menguji pilihan dari kiri ke kanan, sehingga pilihan yang lebih spesifik ditulis lebih dahulu atau dijepit batas kata.
  • Pola terstruktur dengan anchor dan grup bernama mengubah baris log menjadi potongan bernama yang siap diproses.

Referensi#