awk dan sed adalah dua alat klasik untuk mengolah teks baris per baris, langsung dari terminal, tanpa membuka editor. Bayangin setumpuk struk belanja. awk itu seperti menyalin satu kolom dari tiap struk, misalnya totalnya saja. sed itu seperti "cari dan ganti" di editor, tapi dijalankan ke setiap baris sekaligus.
🧪 Tebakan cepat: baris
2024-01-15 ERROR user.service Connection faileddikirim kesed 's/-/./'. Hasilnya2024.01.15atau2024.01-15? Tebak dulu, jawabannya ada di bagian "sed: cari dan ganti".
File contoh: app.log
Semua contoh di pelajaran ini memakai app.log, log sebuah server yang isinya 4 baris:
2024-01-15 ERROR user.service Connection failed
2024-01-15 INFO auth.service Login success
2024-01-16 ERROR db.service Timeout
2024-01-16 WARN cache.service Memory high
awk: ambil kolom
awk membaca file baris demi baris, lalu memecah tiap baris di spasi jadi beberapa field (kolom). Field pertama $1, kedua $2, dan seterusnya. $0 adalah seluruh baris. Baris pertama terpecah begini:
$1 |
$2 |
$3 |
$4 |
$5 |
|---|---|---|---|---|
| 2024-01-15 | ERROR | user.service | Connection | failed |
$ awk '{print $2}' app.log
ERROR
INFO
ERROR
WARN
'{print $2}'adalah program awk-nya: untuk setiap baris, cetak field ke-2. Bungkus dengan tanda kutip satu, supaya shell gak menyentuh$2.print $1, $3mencetak dua field dipisah satu spasi:2024-01-15 user.service.- Field yang gak ada jadi teks kosong. Baris ketiga cuma punya 4 field, jadi
awk '{print $5}' app.logmencetak baris kosong di urutan ketiga. NFberisi jumlah field di baris itu,NRnomor barisnya.
Mau baris tertentu saja? Tulis pola di depan kurung kurawal:
$ awk '/ERROR/ {print $3}' app.log
user.service
db.service
/ERROR/ artinya "cuma baris yang memuat ERROR". Hasilnya sama dengan grep ERROR app.log | awk '{print $3}': saring dulu, baru ambil kolom.
Untuk file yang kolomnya dipisah koma (CSV), ganti pemisahnya dengan -F:
$ echo "Alice,30,Jakarta" | awk -F',' '{print $2}'
30
sed: cari dan ganti
sed (stream editor) menjalankan perintah ke setiap baris. Yang paling sering dipakai s, substitute: s/cari/ganti/.
$ sed 's/-/./' app.log
2024.01-15 ERROR user.service Connection failed
2024.01-15 INFO auth.service Login success
2024.01-16 ERROR db.service Timeout
2024.01-16 WARN cache.service Memory high
$ sed 's/-/./g' app.log
2024.01.15 ERROR user.service Connection failed
2024.01.15 INFO auth.service Login success
2024.01.16 ERROR db.service Timeout
2024.01.16 WARN cache.service Memory high
Tanpa g, sed cuma mengganti kemunculan pertama di tiap baris, jadi tanggalnya jadi 2024.01-15. Flag g (global) mengganti semuanya. Itu jawaban tebakannya.
Perintah sed lain yang sering dipakai:
sed 's/2024-01-15/REDACTED/' app.log # ganti tanggal itu dengan REDACTED
sed '/INFO/d' app.log # hapus baris yang memuat INFO
sed -n '2,3p' app.log # cetak baris 2 sampai 3 saja
- sed gak mengubah file-nya, dia cuma mencetak hasilnya ke layar. Untuk menyimpan, arahkan ke file lain (
> bersih.log) atau pakai-iuntuk mengubah file langsung:sed -i 's/-/./g' app.logdi Linux,sed -i '' 's/-/./g' app.logdi macOS. - Bagian "cari" adalah regex:
.artinya karakter apa saja. Untuk titik sungguhan, tulis\..
Gabung dengan pipe: sort dan uniq
$ awk '{print $2}' app.log | sort | uniq -c
2 ERROR
1 INFO
1 WARN
sortmengurutkan baris, jadi baris yang sama jadi bersebelahan.uniqmembuang baris kembar yang bersebelahan, dan-cmenghitungnya. Tanpasort, urutan ERROR, INFO, ERROR tetap tiga baris terpisah.- Pola yang sama untuk mengambil kolom pertama CSV tanpa duplikat:
awk -F',' '{print $1}' data.csv | sort | uniq.
Dari terminal ke JavaScript
Latihannya menulis ulang cara kerja ini di JavaScript, dengan 4 baris log yang sama:
| Di terminal | Di JavaScript, untuk tiap baris line |
|---|---|
awk '{print $2}' |
line.split(" ")[1] (index mulai dari 0, kolom awk mulai dari 1) |
grep ERROR lalu awk '{print $3}' |
filter dengan line.includes("ERROR") dulu, baru ambil kolom |
sed 's/2024-01-15/REDACTED/g' |
line.split("2024-01-15").join("REDACTED") |
split(teks).join(pengganti) mengganti semua kemunculan, persis seperti flag g.
⚠️ Jebakan yang sering ketemu
- Tanda kutip dua di awk. Di
awk "{print $2}" app.log, shell mengganti$2dengan isinya yang kosong, jadi awk menerima{print }dan mencetak seluruh baris. Pakai tanda kutip satu. - Lupa
g.s/-/./cuma mengganti tanda-yang pertama di tiap baris. uniqtanpasort. Duplikat yang gak bersebelahan gak dibuang.sed -isebelum dicoba. File-nya langsung berubah. Jalankan dulu tanpa-i, cek hasilnya, baru tambahkan-i.
TL;DR: awk memecah tiap baris jadi field: $1, $2, ..., $0 seluruh baris. awk '{print $2}' app.log mengambil kolom ke-2, awk '/ERROR/ {print $3}' cuma dari baris yang memuat ERROR, dan -F',' mengganti pemisahnya untuk CSV. Field yang gak ada jadi kosong. sed 's/cari/ganti/' mengganti kemunculan pertama di tiap baris, tambah g untuk semuanya. sed '/INFO/d' menghapus baris, dan sed baru mengubah file kalau diberi -i. sort | uniq -c menghitung baris kembar, karena uniq cuma membuang yang bersebelahan. Selalu bungkus program awk dan sed dengan tanda kutip satu.