Pemrosesan Teks Dasar

Pemrosesan Teks Dasar

Bitnesia • Aug 30, 2026 74 •EN

Script-script yang kita susun sejak Bab 5 sampai Bab 8 sudah bisa membaca input, mengulang proses lewat loop, dan membungkus logika berulang ke dalam fungsi. Satu kebutuhan yang hampir selalu muncul begitu script menyentuh dunia nyata belum kita bahas tuntas: bagaimana cara mencari, menyaring, dan mengubah teks itu sendiri, baik teks yang tersimpan di file log, output sebuah perintah, maupun string yang sudah ada di dalam variabel. Sysadmin butuh ini untuk menyisir ribuan baris log mencari satu error spesifik. Developer butuh ini untuk memvalidasi format input sebelum diproses lebih lanjut. User biasa pun butuh ini sekadar untuk mencari file mana saja yang mengandung kata tertentu. Bab ini membahas fondasi pemrosesan teks (text processing) di Bash: peta konsep tiga tool utama yang akan menemani kita sepanjang sisa series ini (grep, sed, awk), cara mencari pola dengan grep beserta opsi-opsi yang paling sering dipakai, regular expression dasar secukupnya untuk kebutuhan pencarian sehari-hari, dan manipulasi string bawaan Bash sendiri tanpa perlu memanggil tool eksternal sama sekali. Pembahasan sed dan awk yang lebih mendalam menyusul di Bab 10 dan Bab 11.

9.1 Peta Konsep Tools Pemrosesan Teks di Bash

Sebelum masuk ke praktik, kita perlu tahu peta besar tiga tool pemrosesan teks yang paling sering dipakai berdampingan dengan Bash, supaya kita bisa memilih tool yang tepat untuk kebutuhan tertentu, alih-alih memaksakan satu tool untuk semua kasus. Ketiganya bukan bagian dari builtin Bash, melainkan program eksternal yang hampir selalu tersedia di semua distro Linux, macOS, dan WSL, tapi biasa dipanggil dari dalam script Bash sebagai bagian tak terpisahkan dari alur kerja sehari-hari.

9.1.1 grep untuk Mencari Pola

grep adalah tool yang tugasnya satu: mencari baris yang cocok dengan sebuah pola, lalu menampilkan baris itu. Nama grep sendiri berasal dari perintah editor ed zaman Unix awal, g/re/p (globally search for a regular expression and print), dan sampai sekarang perilakunya tetap setia pada asal-usul itu. grep paling cocok dipakai saat kita hanya perlu tahu "baris mana saja yang mengandung X", tanpa perlu mengubah isinya.

9.1.2 sed untuk Mengubah Teks sebagai Stream

sed (stream editor) memproses teks baris demi baris seperti grep, tapi tugas utamanya mengubah isi teks, bukan sekadar mencarinya, misalnya mengganti semua kemunculan satu kata dengan kata lain di dalam sebuah file konfigurasi. sed dibahas tuntas di Bab 10.

9.1.3 awk untuk Mengolah Data Terstruktur

awk adalah bahasa pemrosesan teks tersendiri yang bekerja berdasarkan kolom (field), paling unggul saat data punya struktur berulang, misalnya file CSV atau log yang tiap barisnya dipisah spasi/koma menjadi beberapa kolom bermakna. awk dibahas tuntas di Bab 11.

Ketiganya sering dipakai bersamaan lewat pipe (Bab 5.3) dalam satu alur kerja, misalnya menyaring baris relevan dulu dengan grep, baru diolah lebih lanjut dengan awk. Tabel berikut merangkum kapan masing-masing paling cocok dipakai.

ToolFungsi UtamaPaling Cocok untuk
grepMencari baris yang cocok polaMenyaring log, mencari string dalam file/output
sedMengubah teks per baris (stream)Substitusi teks massal, edit file konfigurasi
awkMengolah data per kolom (field)Laporan, rekap dari data tabular seperti CSV/log

9.2 grep: Mencari Pola dalam File dan Output

Sub-bab ini membahas cara memakai grep untuk mencari pola, baik langsung di dalam file maupun di output perintah lain lewat pipe, beserta opsi-opsi yang paling sering dipakai di lapangan.

9.2.1 Sintaks Dasar dan Pencarian dalam File

Bentuk paling dasar grep menerima dua argumen: pola yang dicari, dan file tempat mencarinya.

grep "error" /var/log/aplikasi.log

Perintah di atas menampilkan setiap baris di /var/log/aplikasi.log yang mengandung teks error, dengan pencarian yang case-sensitive secara default (huruf besar dan kecil dianggap berbeda). grep juga bisa menerima lebih dari satu file sekaligus, dan begitu lebih dari satu file diberikan, grep otomatis menambahkan nama file di depan setiap baris hasil supaya kita tahu baris itu berasal dari file mana.

grep "error" /var/log/aplikasi-1.log /var/log/aplikasi-2.log

9.2.2 Mencari dalam Output Perintah Lain

grep juga membaca dari stdin (Bab 5.2) jika tidak diberi argumen file, sehingga bisa langsung disambungkan lewat pipe ke output perintah lain, salah satu pola pemakaian paling umum di lapangan.

journalctl -u nginx --no-pager | grep -i "failed"
ps aux | grep "nginx"

Perintah journalctl untuk membaca log systemd akan dibahas lebih dalam di Bab 19. Contoh kedua, ps aux | grep "nginx", punya jebakan klasik yang wajib diketahui setiap Sysadmin: proses grep itu sendiri juga muncul di output ps aux, karena baris perintahnya sendiri mengandung kata nginx, sehingga hasilnya kadang menampilkan satu baris "hantu" yang sebenarnya cuma proses grep yang sedang berjalan. Trik lama yang umum dipakai untuk menghindari ini adalah membungkus salah satu huruf pola dengan character class (dibahas di 9.3.2), misalnya grep "[n]ginx", karena baris perintah grep sendiri berisi teks literal [n]ginx yang tidak cocok dengan pola itu. Alternatif yang lebih bersih adalah memakai pgrep nginx, tool terpisah yang memang dirancang khusus mencari proses berdasarkan nama tanpa masalah ini.

9.2.3 Opsi -i, -v, dan -c

Tiga opsi ini yang paling sering dipakai sehari-hari. -i membuat pencarian case-insensitive (mengabaikan perbedaan huruf besar/kecil).

grep -i "error" /var/log/aplikasi.log

Perintah di atas mencocokkan error, Error, ERROR, dan variasi kapitalisasi lainnya sekaligus. -v membalik logika pencarian, menampilkan baris yang tidak cocok dengan pola, berguna misalnya untuk menyingkirkan baris komentar dari file konfigurasi.

grep -v "^#" /etc/ssh/sshd_config

Pola ^# di atas berarti "baris yang diawali karakter #", detail regex yang dibahas lengkap di 9.3.2. -c menampilkan jumlah baris yang cocok, bukan isi barisnya.

grep -c "error" /var/log/aplikasi.log

Satu hal yang wajib diperhatikan soal -c: opsi ini menghitung jumlah baris yang mengandung pola, bukan jumlah total kemunculan pola itu. Sebuah baris yang mengandung kata error sebanyak tiga kali tetap dihitung sebagai satu baris cocok, bukan tiga.

9.2.4 Opsi -n, -r/-R, -w, -l, dan -o

-n menampilkan nomor baris di depan setiap hasil, berguna untuk langsung menunjuk lokasi pasti sebuah baris sebelum diedit lebih lanjut, misalnya dengan sed di Bab 10.

grep -n "error" /var/log/aplikasi.log

-r (atau -R) membuat grep mencari secara rekursif ke dalam sebuah direktori beserta seluruh subdirektorinya, dipakai saat kita perlu mencari satu pola di banyak file sekaligus, misalnya menyisir seluruh script di sebuah folder proyek.

grep -r "TODO" ~/scripts/

Perbedaan halus antara -r dan -R ada pada perlakuan terhadap symbolic link: -r mengikuti symbolic link hanya jika link itu diberikan langsung sebagai argumen di baris perintah, sedangkan -R selalu mengikuti semua symbolic link yang ditemukan selama pencarian rekursif. Perbedaan ini jarang berdampak untuk pemakaian sehari-hari, tapi penting diketahui saat bekerja dengan struktur direktori yang banyak memakai symlink, misalnya direktori /etc di beberapa distro.

-w mencocokkan pola hanya sebagai kata utuh, bukan sebagai bagian dari kata lain.

grep -w "cron" /var/log/aplikasi.log

Tanpa -w, pola cron juga akan cocok dengan kata seperti crontab atau anacron karena keduanya memang mengandung substring cron. Begitu -w ditambahkan, hanya kemunculan cron sebagai kata yang berdiri sendiri yang dihitung cocok. -l hanya menampilkan nama file yang mengandung pola, tanpa menampilkan isi barisnya, cocok dipadukan dengan -r untuk mencari file mana saja yang perlu diperiksa lebih lanjut.

grep -rl "deprecated" ~/scripts/

-o hanya menampilkan bagian teks yang benar-benar cocok dengan pola, bukan seluruh baris, sangat berguna saat dipadukan dengan regex di 9.3 untuk mengekstrak potongan data tertentu dari sebuah baris, misalnya alamat IP dari satu baris log yang panjang.

9.2.5 Troubleshooting: Quoting Pola agar Tidak Diproses Shell

Pola pencarian grep wajib selalu dibungkus tanda kutip, persis aturan quoting variabel yang sudah dibahas di Bab 3.4. Tanpa tanda kutip, shell berisiko lebih dulu menginterpretasi karakter seperti *, $, [, dan ? sebagai pattern ekspansi nama file (Bab 2.2.5), bukan meneruskannya apa adanya ke grep sebagai pola pencarian.

grep [error] /var/log/aplikasi.log
grep "[error]" /var/log/aplikasi.log

Baris pertama berisiko gagal atau menghasilkan hasil yang tidak diduga jika kebetulan ada file di direktori kerja yang namanya cocok dengan pattern [error], karena shell mengekspansinya lebih dulu sebelum grep sempat melihatnya. Baris kedua aman, karena tanda kutip mencegah shell memproses karakter di dalamnya sama sekali. Kebiasaan ini sebaiknya dipegang teguh terutama saat pola pencarian berasal dari variabel yang isinya bisa berubah-ubah, misalnya input dari User.

grep "$pola_pencarian" /var/log/aplikasi.log

Kebiasaan mengutip pola ini juga jadi lapisan pertahanan pertama terhadap perilaku tak terduga saat pola berasal dari sumber yang tidak sepenuhnya bisa dipercaya (misalnya input dari Attacker yang mencoba menyisipkan karakter aneh), topik yang dibahas lebih dalam soal keamanan script di Bab 23.

9.3 Regular Expression Dasar dan Extended

Sub-bab ini membahas regular expression (sering disingkat regex), sederet karakter yang mendefinisikan sebuah pola pencarian teks, secukupnya untuk kebutuhan pencarian sehari-hari dengan grep. Regex adalah fondasi yang juga dipakai sed dan awk di Bab 10 dan Bab 11, jadi memahaminya di sini akan langsung terpakai ulang di dua bab berikutnya.

9.3.1 Apa itu Regular Expression

Berbeda dengan pencarian teks literal biasa yang cuma mencocokkan karakter persis apa adanya, regex memakai karakter-karakter khusus, disebut metakarakter (metacharacter), untuk mendeskripsikan pola yang lebih fleksibel, misalnya "baris yang diawali angka" atau "kata apa saja yang mengandung tiga huruf berurutan". grep memakai regex untuk mencocokkan pola secara default, bukan cuma pencarian teks literal, meski untuk pola yang tidak mengandung metakarakter sama sekali, hasilnya sama saja dengan pencarian literal biasa.

9.3.2 Metakarakter Inti: . * ^ $ dan [ ]

Beberapa metakarakter berikut ini yang paling sering dipakai untuk kebutuhan pencarian sehari-hari.

MetakarakterArtiContoh Pola
.Mencocokkan satu karakter apa sajac.t cocok dengan cat, cut, c9t
*Karakter sebelumnya muncul nol kali atau lebihlo*g cocok dengan lg, log, loog
^Menandai awal baris^error hanya cocok jika baris diawali error
$Menandai akhir bariserror$ hanya cocok jika baris diakhiri error
[ ]Character class, satu karakter dari sekumpulan pilihan[0-9] cocok dengan satu digit angka

Character class juga bisa dinegasikan dengan ^ di posisi pertama di dalam kurung siku, berarti "satu karakter apa saja selain yang disebutkan".

grep "[^0-9]" file_angka.txt

Pola di atas mencocokkan baris yang mengandung setidaknya satu karakter yang bukan angka, berguna misalnya untuk memvalidasi apakah sebuah file seharusnya hanya berisi data numerik ternyata mengandung karakter lain yang tidak diharapkan.

9.3.3 BRE vs ERE dan Opsi -E

grep secara default memakai dialek regex bernama BRE (Basic Regular Expression), salah satu dari dua dialek regex yang didefinisikan spesifikasi POSIX. Dialek satunya, ERE (Extended Regular Expression), diaktifkan lewat opsi -E. Perbedaan paling praktis antara keduanya ada pada metakarakter +, ?, |, (, ), {, dan }: di BRE, karakter-karakter ini dianggap literal kecuali diberi awalan backslash supaya jadi metakarakter, sedangkan di ERE berlaku sebaliknya, karakter-karakter itu langsung jadi metakarakter tanpa perlu backslash.

MetakarakterBRE (default grep)ERE (grep -E)
Satu atau lebih\++
Nol atau satu\??
Alternasi (atau)\||
Grouping\( \)( )
Pengulangan spesifik\{n,m\}{n,m}
grep 'gagal\|error' /var/log/aplikasi.log
grep -E 'gagal|error' /var/log/aplikasi.log

Kedua baris di atas menghasilkan pencarian yang identik, baris pertama pakai BRE dengan \| yang di-escape, baris kedua pakai ERE dengan -E tanpa perlu escape. Variasi program egrep yang sering ditemui di berbagai tutorial lama sebenarnya cuma alias untuk grep -E, dan GNU grep sendiri sudah menandainya usang, jadi grep -E adalah bentuk yang lebih dianjurkan dipakai untuk script baru. Di lapangan, pilih ERE lewat -E saat pola yang dibutuhkan melibatkan alternasi (|) atau pengulangan (+, ?, {n,m}), karena bentuknya jauh lebih mudah dibaca dibanding versi BRE yang penuh backslash.

9.3.4 Studi Kasus: Menyaring Baris Konfigurasi dan Log

Pola yang sangat umum dipakai Sysadmin adalah menyaring file konfigurasi supaya hanya menampilkan baris yang benar-benar aktif, membuang baris komentar dan baris kosong sekaligus.

grep -v "^#" /etc/ssh/sshd_config | grep -v "^$"

Pola ^$ di atas berarti "baris yang langsung diakhiri begitu dimulai", alias baris kosong tanpa karakter sama sekali. Contoh lain, mengekstrak baris log yang tampak seperti alamat IPv4 memakai ERE dan opsi -o dari 9.2.4.

grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' /var/log/akses.log

Perlu jujur diakui, pola di atas hanya memeriksa format angka dipisah titik sebanyak empat kelompok, bukan validasi penuh bahwa tiap kelompok benar-benar berada di rentang 0-255 seperti aturan IPv4 sesungguhnya, sehingga teks seperti 999.999.999.999 tetap dianggap cocok. Untuk kebutuhan pencarian dan penyaringan cepat, pola sesederhana ini biasanya sudah cukup, tapi untuk validasi IPv4 yang benar-benar ketat, pendekatan berbasis awk atau pengecekan tambahan di Bash sendiri (Bab 11) jauh lebih tepat dipakai.

9.4 Manipulasi String Bawaan Bash

Sub-bab penutup ini membahas kemampuan Bash sendiri untuk mengolah string tanpa memanggil tool eksternal seperti grep sama sekali, lewat sintaks parameter expansion yang beberapa bentuknya sempat disinggung sekilas di Bab 3.4. Untuk operasi string yang sederhana, memakai fitur bawaan Bash ini jauh lebih cepat dibanding memanggil proses eksternal, karena tidak ada overhead menjalankan program terpisah.

9.4.1 Panjang String dengan ${#var}

Sintaks ${#nama_variabel} mengembalikan jumlah karakter dalam sebuah string.

nama_host="server-produksi"
echo "${#nama_host}"

Perintah di atas menampilkan 16, jumlah karakter dalam server-produksi. Pemakaian umum di lapangan misalnya memvalidasi panjang input User sebelum diproses lebih lanjut, seperti memastikan nama host yang dimasukkan tidak melebihi batas karakter tertentu.

if [ "${#nama_host}" -gt 63 ]; then
    echo "Error: nama host maksimal 63 karakter" >&2
    exit 1
fi

9.4.2 Ekstraksi Substring dengan ${var:offset:length}

Sintaks ${var:offset:length} mengekstrak sebagian string mulai dari posisi offset (dihitung dari 0) sepanjang length karakter. Bagian :length bersifat opsional, jika dihilangkan hasilnya adalah sisa string sampai akhir.

tanggal="2026-08-30"
tahun="${tanggal:0:4}"
bulan="${tanggal:5:2}"
hari="${tanggal:8:2}"

echo "Tahun: $tahun, Bulan: $bulan, Hari: $hari"

Script di atas menampilkan Tahun: 2026, Bulan: 08, Hari: 30, mengekstrak tiap bagian tanggal berdasarkan posisi karakternya di dalam string berformat YYYY-MM-DD. Satu jebakan yang wajib diketahui: mengambil karakter dari akhir string dengan offset negatif butuh spasi sebelum tanda minus, atau dibungkus kurung.

echo "${tanggal: -2}"
echo "${tanggal:(-2)}"

Tanpa spasi, ${tanggal:-2} justru dikenali sebagai sintaks "nilai default" yang berbeda sama sekali (pola yang sempat dipakai di studi kasus Bab 6.4.4, ${1:-status}), yaitu "pakai nilai 2 jika tanggal kosong atau belum diset", bukan "ambil 2 karakter terakhir". Kedua sintaks itu terlihat mirip tapi maknanya jauh berbeda, jadi spasi (atau kurung) sebelum offset negatif tidak boleh dilewatkan.

9.4.3 Mengganti Teks dengan ${var/pola/pengganti}

Sintaks ${var/pola/pengganti} mengganti kemunculan pertama pola di dalam var dengan pengganti, sedangkan ${var//pola/pengganti} (dua garis miring) mengganti semua kemunculannya.

path_file="/home/user/laporan-lama.txt"
echo "${path_file/lama/baru}"

Perintah di atas menampilkan /home/user/laporan-baru.txt. Untuk kasus yang butuh mengganti seluruh kemunculan sekaligus, misalnya menormalkan pemisah dalam sebuah string.

daftar="nginx,mysql,redis"
echo "${daftar//,/ }"

Baris di atas mengganti setiap koma dengan spasi, menghasilkan nginx mysql redis. Dua variasi tambahan yang berguna: ${var/#pola/pengganti} hanya mengganti jika pola cocok tepat di awal string, dan ${var/%pola/pengganti} hanya mengganti jika pola cocok tepat di akhir string.

nama_file="backup_database.tar.gz"
echo "${nama_file/%.tar.gz/.bak}"

9.4.4 Case Conversion: Huruf Besar dan Kecil

Sejak Bash 4.0, tersedia sintaks bawaan untuk mengubah case huruf tanpa memanggil tool eksternal seperti tr. ${var^} mengubah huruf pertama jadi kapital, ${var^^} mengubah seluruh huruf jadi kapital, ${var,} mengubah huruf pertama jadi huruf kecil, dan ${var,,} mengubah seluruh huruf jadi huruf kecil.

layanan="NGINX"
echo "${layanan,,}"

nama="produksi"
echo "${nama^}"

Baris pertama menampilkan nginx, baris kedua menampilkan Produksi. Pemakaian yang sering ditemui di lapangan adalah menormalkan input User sebelum dibandingkan, misalnya pada konfirmasi y/n yang polanya sudah muncul di Bab 5.1, supaya jawaban Y, y, maupun Yes tetap dikenali sama.

read -r -p "Lanjutkan proses? (y/n): " jawaban
jawaban="${jawaban,,}"

if [ "$jawaban" = "y" ]; then
    echo "Melanjutkan proses..."
fi

Karena fitur ini baru tersedia mulai Bash 4.0, script yang perlu tetap kompatibel dengan Bash versi lama (misalnya Bash bawaan macOS yang masih versi 3.2 seperti disebutkan di Bab 1.3.2, sebelum diperbarui lewat Homebrew) sebaiknya memakai tr '[:upper:]' '[:lower:]' sebagai alternatif yang lebih portable.

9.4.5 Troubleshooting: Pattern di Bash Itu Glob, Bukan Regex

Satu kesalahpahaman yang sering menjebak: pola di dalam ${var/pola/pengganti} bukan regex seperti yang dipakai grep di 9.3, melainkan glob pattern, jenis pola yang sama seperti dipakai ekspansi nama file di Bab 2.2.5 (*, ?, [...]). Metakarakter regex seperti +, |, atau {n,m} tidak dikenali di dalam parameter expansion ini, dan akan diperlakukan sebagai karakter literal biasa.

teks="tes123"
echo "${teks/[0-9]+/X}"

Pola [0-9]+ di atas tidak berarti "satu digit atau lebih" seperti di regex. Karena + bukan metakarakter glob, pola itu dibaca sebagai "satu karakter angka apa saja, diikuti karakter + literal", yang jelas tidak cocok dengan tes123, sehingga string keluar tanpa perubahan sama sekali. Saat kebutuhan penggantian teks memang membutuhkan kekuatan regex sesungguhnya, misalnya pola berulang atau alternasi, sed di Bab 10 adalah pilihan yang tepat, karena sed memang dirancang khusus untuk substitusi teks berbasis regex, bukan sekadar glob sederhana seperti parameter expansion Bash.