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.
| Unsur | Arti |
|---|---|
\d | Satu 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.
#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;
}2026-01-15 24.5 -> cocok
15-01-2026 24.5 -> tidak cocok
2026-01-16 25.0 -> cocok
catatan tanpa format -> tidak cocokBaris 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.
#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;
}Baris : 2026-01-15 24.5
Tanggal : 2026-01-15
Suhu : 24.5Perintah berikut mengompilasi dan menjalankan salah satu program contoh di terminal.
# kompilasi ekstraksi.cpp dan simpan biner di /tmp
g++ ekstraksi.cpp -o /tmp/ekstraksi
# jalankan program hasil kompilasi
/tmp/ekstraksiBaris : 2026-01-15 24.5
Tanggal : 2026-01-15
Suhu : 24.5Mengganti 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.
// 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_matchuntuk mencari bagian di dalam string. Fungsi ini menuntut kesesuaian penuh dari awal sampai akhir, sehingga kecocokan parsial selalu gagal. Gunakanregex_searchapabila 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::regexdi dalam perulangan yang panjang. Pola dikompilasi ulang pada setiap iterasi dan program melambat jauh tanpa alasan. Pindahkan deklarasinya ke luar perulangan dan jadikanconst.
Ringkasan#
- Pola dikompilasi menjadi objek
std::regex, dan raw string literalR"(...)"menjaga pola tetap bebas escape ganda. regex_matchmenuntut kesesuaian penuh untuk validasi, sedangkanregex_searchmencari kecocokan parsial dan mengisinya kestd::smatchdengan 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#
- Regular expressions library — cppreference — Ikhtisar pustaka regex beserta kelas, algoritma, dan pilihan tata bahasanya.
- std::regex_match — cppreference — Aturan kesesuaian penuh string terhadap pola.
- std::regex_replace — cppreference
— Pemakaian penanda
$nsaat mengganti bagian yang cocok.