Regex (pengenalan)

Dasar <regex> dan pertimbangan memakainya untuk pekerjaan nyata.

Daftar isi

Topik ini membahas pustaka <regex> sebagai pengantar pencocokan pola teks di C++: menulis pola, memeriksa kesesuaian string, menangkap bagian yang cocok, dan mengganti teks berdasarkan pola. Contoh yang digunakan adalah validasi baris log sensor suhu yang berformat tetap. Topik ini juga menutup dengan pertimbangan jujur mengenai kapan <regex> layak dipakai dan kapan penulis parser eksplisit menjadi pilihan yang lebih baik.

Pola dan raw string literal#

Pustaka <regex> mengimplementasikan regular expression (regex), yaitu notasi untuk mendeskripsikan pola teks, dengan tata bahasa default ECMAScript. Sebuah pola dikompilasi menjadi objek std::regex terlebih dahulu, kemudian objek itu dipakai berulang kali untuk memeriksa banyak string. Karena pola memakai karakter khusus seperti tanda kurung dan garis miring terbalik, tulis pola di dalam raw string literal berbentuk R"(...)" agar karakternya tidak perlu di-escape ganda.

Beberapa unsur pola yang paling sering dipakai dirangkum pada tabel berikut.

UnsurArti
\dSatu karakter angka
\{n\}Unsur sebelumnya diulang tepat n kali
+Unsur sebelumnya muncul satu kali atau lebih
.Satu karakter apa pun
(...)Kelompok tangkapan untuk bagian yang cocok
^ dan $Batas awal dan akhir string

Pola R"(\d{4}-\d{2}-\d{2})" misalnya menandai empat angka, tanda hubung, dua angka, tanda hubung, lalu dua angka lagi, yaitu bentuk tanggal 2026-01-15. Tanpa raw string literal, pola yang sama harus ditulis "\\d{4}-\\d{2}-\\d{2}", dan tanda garis miring terbalik ganda tersebut adalah sumber error yang umum. Cara membaca pola selalu dari kiri ke kanan: karakter biasa dicocokkan apa adanya, sedangkan karakter yang bermakna khusus seperti titik dan tanda kurung ditulis dengan garis miring terbalik di depannya agar dibaca sebagai karakter biasa.

Memeriksa kesesuaian dengan regex_match#

Fungsi std::regex_match memeriksa apakah seluruh string sesuai dengan pola, dari karakter pertama sampai karakter terakhir. Fungsi ini mengembalikan bool sehingga cocok untuk validasi format. Program berikut menyaring baris log sensor suhu, yaitu tanggal berformat ISO yang diikuti satu bacaan suhu.

cpp validasi.cpp
#include <iostream>
#include <regex>
#include <string>
#include <vector>

int main() {
    // pola: tanggal ISO sederhana diikuti satu bacaan suhu,
    // misalnya "2026-01-15 24.5"
    const std::regex pola(R"(\d{4}-\d{2}-\d{2} \d{1,2}\.\d)");

    const std::vector<std::string> log = {
        "2026-01-15 24.5",
        "15-01-2026 24.5",
        "2026-01-16 25.0",
        "catatan tanpa format",
    };

    for (const std::string& baris : log) {
        const bool cocok = std::regex_match(baris, pola);
        std::cout << baris << "  ->  " << (cocok ? "cocok" : "tidak cocok") << "\n";
    }
    return 0;
}
text Keluaran
2026-01-15 24.5  ->  cocok
15-01-2026 24.5  ->  tidak cocok
2026-01-16 25.0  ->  cocok
catatan tanpa format  ->  tidak cocok

Baris kedua ditolak karena urutan hari dan bulannya terbalik, sedangkan baris terakhir ditolak karena tidak memuat pola tanggal sama sekali. Perhatikan bahwa pola suhu ditulis \d{1,2}\.\d, dan tanda titik yang berarti karakter apa pun harus ditulis \. agar benar-benar berarti titik desimal.

Syarat kesesuaian penuh ini membedakan regex_match dari banyak alat pencarian teks yang secara default mencari kecocokan parsial. Apabila baris log kelak ditambah stempel waktu di depannya, pola yang sama akan menolak seluruh baris, dan pilihan yang tepat berpindah ke regex_search. Pemilihan antara keduanya bergantung pada satu hal, yaitu apakah pola dimaksudkan sebagai definisi format utuh atau sekadar penanda keberadaan bagian tertentu di dalam teks.

Menangkap bagian pola dengan smatch#

Fungsi std::regex_search mencari bagian string yang sesuai dengan pola, dan hasilnya disimpan dalam objek std::smatch. Kelompok tangkapan yang ditulis dalam tanda kurung dapat dibaca melalui indeks: hasil[0] berisi keseluruhan bagian yang cocok, hasil[1] berisi kelompok pertama, dan seterusnya. Fungsi anggota str() mengubah setiap bagian menjadi std::string yang siap diproses lebih lanjut. Apabila tidak ada bagian yang cocok, regex_search mengembalikan false dan objek smatch tidak boleh dibaca, sehingga pemeriksaan nilai kembali wajib dilakukan sebelum mengakses indeksnya.

cpp ekstraksi.cpp
#include <iostream>
#include <regex>
#include <string>

int main() {
    const std::string baris = "2026-01-15 24.5";
    // dua kelompok tangkapan: tanggal, lalu suhu
    const std::regex pola(R"((\d{4}-\d{2}-\d{2}) (\d+\.\d))");
    std::smatch hasil;

    if (std::regex_search(baris, hasil, pola)) {
        std::cout << "Baris   : " << hasil[0].str() << "\n";
        std::cout << "Tanggal : " << hasil[1].str() << "\n";
        std::cout << "Suhu    : " << hasil[2].str() << "\n";
    } else {
        std::cout << "Pola tidak ditemukan\n";
    }
    return 0;
}
text Keluaran
Baris   : 2026-01-15 24.5
Tanggal : 2026-01-15
Suhu    : 24.5

Perintah berikut mengompilasi dan menjalankan salah satu program contoh di terminal.

bash
# kompilasi ekstraksi.cpp dan simpan biner di /tmp
g++ ekstraksi.cpp -o /tmp/ekstraksi
# jalankan program hasil kompilasi
/tmp/ekstraksi
text Keluaran
Baris   : 2026-01-15 24.5
Tanggal : 2026-01-15
Suhu    : 24.5

Mengganti teks dan batas pemakaian#

Fungsi std::regex_replace menghasilkan string baru berupa salinan masukan yang bagian cocoknya diganti, dan penanda $1 serta $2 merujuk kelompok tangkapannya. String masukan tidak diubah, sehingga hasil penggantian perlu disimpan pada variabel yang berbeda.

cpp Contoh: mengganti bagian yang cocok dengan regex_replace
// tidak-dijalankan (fragmen, bukan program utuh)
const std::regex pola(R"((\d{4}-\d{2}-\d{2}) (\d+\.\d))");
const std::string baris = "2026-01-15 24.5";

// penanda $1 dan $2 merujuk kelompok tangkapan pertama dan kedua
const std::string rapi = std::regex_replace(baris, pola, "$1; suhu $2");
std::cout << rapi << "\n";  // mencetak "2026-01-15; suhu 24.5"

Pustaka ini memiliki batasan yang perlu diketahui sebelum dipakai. Implementasi <regex> dikenal berbiaya besar saat kompilasi pola dan lebih lambat daripada pemeriksaan manual yang sederhana. Pustaka ini juga turut memperbesar ukuran biner program. Karena itu pustaka ini layak dipakai untuk validasi format yang jarang berjalan, bukan untuk memproses jutaan baris per detik. Untuk pekerjaan nyata yang strukturnya berlapis, seperti format berkas dengan bagian dan kutipan bertingkat, tulis parser eksplisit yang membaca string selangkah demi selangkah, karena logikanya lebih mudah diuji dan pesan errornya lebih terarah. Regex yang panjang dan bersarang cenderung sulit dibaca kembali, sehingga pemecahan pola menjadi beberapa tahap sederhana lebih dipilih daripada satu pola raksasa.

Kesalahan umum#

  • Menggunakan regex_match untuk mencari bagian di dalam string. Fungsi ini menuntut kesesuaian penuh dari awal sampai akhir, sehingga kecocokan parsial selalu gagal. Gunakan regex_search apabila pola hanya perlu ditemukan di bagian mana pun dari string.
  • Menulis pola di dalam string literal biasa. Setiap garis miring terbalik harus ditulis dua kali, dan kelalaian kecil di sini mengubah arti pola tanpa terlihat. Gunakan raw string literal R"(...)" agar pola terbaca seperti pada alat regex lain.
  • Membangun objek std::regex di dalam perulangan yang panjang. Pola dikompilasi ulang pada setiap iterasi dan program melambat jauh tanpa alasan. Pindahkan deklarasinya ke luar perulangan dan jadikan const.

Ringkasan#

  • Pola dikompilasi menjadi objek std::regex, dan raw string literal R"(...)" menjaga pola tetap bebas escape ganda.
  • regex_match menuntut kesesuaian penuh untuk validasi, sedangkan regex_search mencari kecocokan parsial dan mengisinya ke std::smatch dengan kelompok tangkapan bernomor.
  • <regex> tepat untuk validasi format sederhana yang jarang berjalan, sedangkan pekerjaan parsing berlapis dan berperforma tinggi lebih cocok ditangani parser eksplisit.

Referensi#