Teks dunia nyata jarang berwujud kalimat lurus: ada baris baru, tab, tanda kutip di dalam kutip, backslash jalur berkas, dan emoji yang tidak ada di papan ketik. Rust menyediakan dua mekanisme yang saling melengkapi untuk menampung semuanya. Escape sequence menuliskan karakter khusus lewat kombinasi backslash di dalam string biasa, sedangkan raw string melakukan kebalikannya: menonaktifkan seluruh escape sehingga teks ditangkap apa adanya. Pilihan yang tepat membuat kode berkas konfigurasi, cuplikan JSON, atau regex terbaca bersih alih-alih hutan backslash ganda. Chapter ini menutup Section dengan kedua mekanisme tersebut beserta batas-batasnya.
Escape Sequence untuk Karakter Khusus #
Di dalam string biasa, backslash memulai escape sequence — isyarat bahwa karakter berikutnya bukan huruf biasa. Escape \n menjadi baris baru, \t menjadi tab, \" memungkinkan kutip ganda hidup di dalam string berbatas kutip ganda, \\ menjadi satu backslash. Dua bentuk khusus melompat ke kode numerik: \x41 merujuk byte ASCII heksadesimal, dan \u{1F980} merujuk code point Unicode — format yang sudah kita lihat sekilas di Chapter Iterasi String:
fn main() {
println!("baris pertama\nbaris kedua");
println!("kolom satu\tkolom dua");
println!("kutip dalam teks: \"Halo\"");
println!("backslash: C:\\Users\\Budi");
println!("huruf \x41 dan kepiting \u{1F980}");
let crab = '\u{1F980}';
println!("maskot: {}", crab);
}Output yang Dihasilkan:
baris pertama
baris kedua
kolom satu kolom dua
kutip dalam teks: "Halo"
backslash: C:\Users\Budi
huruf A dan kepiting 🦀
maskot: 🦀Mari kita bedah kode di atas baris per baris:
- Baris 2 (
println!("baris pertama\nbaris kedua");): satu string berisi escape\ntercetak sebagai dua baris output — karakter baris baru benar-benar masuk ke isi teks, bukan sekadar tampilan. - Baris 3 (
println!("kolom satu\tkolom dua");):\tmenjadi satu karakter tab; di output terlihat sebagai jarak lebar antara kedua kolom. - Baris 4 (
println!("kutip dalam teks: \"Halo\"");):\"menempatkan kutip ganda di dalam teks tanpa menutup string — outputnya"Halo"di tengah kalimat. - Baris 5 (
println!("backslash: C:\\Users\\Budi");):\\runtuh menjadi satu backslash, jadi jalur berkas tampil utuh sebagaiC:\Users\Budi. - Baris 6 (
println!("huruf \x41 dan kepiting \u{1F980}");):\x41men-decode byte heksadesimal 0x41 menjadi hurufA, sedangkan\u{1F980}merujuk code point kepiting 🦀 — karakter empat byte yang tidak mungkin diketik langsung dari kebanyakan papan ketik. - Baris 7-8 (
let crab = '\u{1F980}';): escape Unicode juga berlaku pada character literal dengan kutip tunggal;crabbertipechardan dicetak biasa dengan{}.
Rangkuman escape yang paling sering dipakai:
| Escape | Makna |
|---|---|
\n | baris baru |
\r | carriage return |
\t | tab |
\\ | backslash |
\" | kutip ganda |
\' | kutip tunggal |
\x41 | byte ASCII (hanya 00–7F) |
\u{1F980} | code point Unicode apa pun |
Raw String untuk Teks Mentah #
Raw string membuka dengan huruf r sebelum kutip, dan efeknya radikal: backslash tidak lagi berarti apa pun. Teks ditangkap mentah — tiap backslash, kutip, dan baris tetap menjadi karakter isi. Ketika teks perlu mengandung kutip ganda, raw string dinaikkan kadarnya dengan tanda pagar: r#"..."# mengizinkan kutip ganda di dalam; r##"..."## mengizinkan pula kombinasi "# di dalam; dan seterusnya:
fn main() {
let path = r"C:\Users\Budi\Documents";
println!("path: {}", path);
let json = r#"{"name": "Budi", "age": 30}"#;
println!("json: {}", json);
let quote = r#"Budi berkata: "Rust itu asyik""#;
println!("quote: {}", quote);
let tricky = r##"pattern "# di dalam teks"##;
println!("tricky: {}", tricky);
}Output yang Dihasilkan:
path: C:\Users\Budi\Documents
json: {"name": "Budi", "age": 30}
quote: Budi berkata: "Rust itu asyik"
tricky: pattern "# di dalam teksMari kita telaah baris-barisnya:
- Baris 2 (
let path = r"C:\Users\Budi\Documents";): setiap backslash tersimpan apa adanya. Bandingkan dengan string biasa di contoh sebelumnya yang harus menulis\\untuk hasil yang sama — raw string menghapus seluruh kebisingan itu. - Baris 4 (
let json = r#"{"name": "Budi", "age": 30}"#;): pembatasr#"..."#membuat kutip ganda di dalam teks tidak menutup string, sehingga cuplikan JSON ditulis persis seperti bentuk jadinya. - Baris 6 (
let quote = r#"Budi berkata: "Rust itu asyik""#;): kutip ganda di ujung kalimat pun aman — penutup string baru terjadi pada kombinasi tanda pagar plus kutip,"#. - Baris 8 (
let tricky = r##"pattern "# di dalam teks"##;): karena isinya mengandung kombinasi"#, kadar dinaikkan menjadir##..."##. Aturannya: pilih jumlah tanda pagar lebih banyak daripada kombinasi pagar-kutip terpanjang di dalam teks.
Saat Escape Berhenti Bekerja di Raw String #
Konsekuensi menonaktifkan backslash harus dipahami tuntas: escape sequence tidak lagi aktif, termasuk \n. Teks mentah yang mengandung \n akan menyimpan dua karakter — backslash dan huruf n — bukan satu baris baru:
fn main() {
let raw = r"teks dengan \n tidak menjadi baris baru";
println!("raw: {}", raw);
let normal = "teks dengan \n menjadi baris baru";
println!("normal: {}", normal);
}Output yang Dihasilkan:
raw: teks dengan \n tidak menjadi baris baru
normal: teks dengan
menjadi baris baruBedah singkatnya:
- Baris 2-3 (
let raw = r"..."):\ndi dalam raw string tercetak sebagai dua karakter literal — baris output tetap satu dan teks tampak persis seperti yang ditulis. - Baris 4-5 (
let normal = "..."; println!("normal: {}", normal);): string biasa menerjemahkan\nmenjadi baris baru, sehingga output terbelah dua baris; spasi sebelum dan sesudah pemisah ikut terbawa apa adanya.
Raw String Multibaris dan Byte String #
Raw string memang boleh berbaris-baris di kode sumber, dan setiap baris plus indentasinya tersimpan apa adanya. Satu anggota keluarga lain patut dikenal sejak sekarang: byte string dengan awalan b, yang menghasilkan barisan u8 — bukan teks — dan cocok dipadukan dengan lensa byte dari Chapter Iterasi String:
fn main() {
let banner = r#" =================
BELAJAR RUST
================="#;
println!("{}", banner);
let data = b"Halo";
println!("byte string: {:?}", data);
}Output yang Dihasilkan:
=================
BELAJAR RUST
=================
byte string: [72, 97, 108, 111]Mari kita bedah kode di atas:
- Baris 2-4 (
let banner = r#"..."#;): banner tiga baris ditulis langsung dalam kode sumber; dua spasi di depan setiap baris ikut tersimpan sehingga output membentuk bingkai rata tengah. Format debug{:#?}dari Chapter Formatting tidak dibutuhkan — teks memang sudah multi-baris. - Baris 6 (
let data = b"Halo";): awalanbmengubah literal menjadi barisan byte. Isinya tetap karakter ASCIIH,a,l,o, tetapi tipenya bukan&str. - Baris 7 (
println!("byte string: {:?}", data);): format debug menampilkan kebenarannya —[72, 97, 108, 111], empat angka byte yang persis sama dengan hasil iterasibytes()pada"Halo". Byte string hanya boleh berisi ASCII; karakter non-ASCII tetap harus lewat\u{...}di string biasa.
Ringkasan #
Escape sequence membawa karakter khusus ke dalam string biasa: \n, \t, \", \\, byte ASCII \x41, dan code point Unicode \u{1F980}. Raw string menangkap teks mentah dengan menonaktifkan seluruh escape — backslash dan kutip tersimpan apa adanya — dengan kadar tanda pagar yang dinaikkan r#"..."#, r##"..."## sesuai kebutuhan, dan multi-baris ditulis langsung di kode sumber. Kompromi wajibnya: \n tidak bekerja di raw string, dan byte string b"..." menghasilkan barisan u8, bukan teks. Dengan format! di satu tangan dan raw string di tangan lain, kotak perkakas teks kita lengkap — cukup untuk membangun antarmuka berbasis teks yang rapi, aman, dan terbaca.