awk

Pengolahan berbasis kolom dengan awk, dari pencetakan kolom sampai one-liner perhitungan.

Daftar isi

awk adalah bahasa pemrograman kecil yang dirancang untuk memproses teks berbasis kolom, yaitu baris yang terbagi menjadi medan (field) yang dipisahkan spasi atau tanda lain. Dalam bentuk paling ringkas, awk dipakai sebagai one-liner, yakni program satu baris yang ditulis langsung di terminal untuk mencetak, menyaring, atau menghitung kolom. Topik ini membahas model pola dan aksi, pemilihan medan, pemisah medan, penyaringan bersyarat, serta one-liner perhitungan.

Pola dan aksi#

Bentuk dasar program awk adalah pola { aksi }. awk membaca masukan baris demi baris, memecah setiap baris menjadi medan bernomor, lalu menjalankan aksi apabila baris tersebut memenuhi pola. Medan pertama bernama $1, medan kedua $2, dan seterusnya, sedangkan $0 berisi satu baris utuh. Pola boleh ditiadakan, dan tanpa pola aksi dijalankan untuk setiap baris.

bash
# menyiapkan folder kerja dan berkas contoh
mkdir -p /tmp/kerja-awk
cd /tmp/kerja-awk
printf 'Ali 78\nBudi 85\nCitra 92\nDewi 81\nEko 74\n' > nilai.txt
cat nilai.txt
text Keluaran
Ali 78
Budi 85
Citra 92
Dewi 81
Eko 74
bash
cd /tmp/kerja-awk
# mencetak medan pertama dari setiap baris
awk '{print $1}' nilai.txt
# mencetak medan kedua lalu medan pertama
awk '{print $2, $1}' nilai.txt
text Keluaran
Ali
Budi
Citra
Dewi
Eko
78 Ali
85 Budi
92 Citra
81 Dewi
74 Eko

Perintah pertama hanya mencetak kolom nama, sedangkan perintah kedua menukar urutan kolom menjadi nilai lalu nama. Perhatikan bahwa tanda koma di antara $2 dan $1 memisahkan dua argumen print dengan spasi, sedangkan penulisan $2 $1 tanpa koma akan menyambung keduanya tanpa spasi.

Memisahkan medan dengan -F#

Secara bawaan awk memisah medan pada spasi dan tab. Untuk berkas yang memakai pemisah lain, misalnya koma pada berkas CSV, opsi -F perlu ditambahkan, diikuti karakter pemisahnya. Contoh berikut memakai stok.csv yang memuat nama barang dan jumlah stoknya.

bash
cd /tmp/kerja-awk
# menyiapkan berkas CSV kecil
printf 'pensil,35\nbuku,48\npenghapus,27\npenggaris,19\n' > stok.csv
# mencetak kolom stok dengan pemisah koma
awk -F',' '{print $2}' stok.csv
# mencetak kedua kolom dengan label
awk -F',' '{print $1 ": " $2}' stok.csv
text Keluaran
35
48
27
19
pensil: 35
buku: 48
penghapus: 27
penggaris: 19

Tanpa -F',', awk akan memperlakukan satu baris utuh sebagai medan pertama karena tidak ada spasi di dalamnya, sehingga $2 bernilai kosong. Karakter setelah -F ditulis berdampingan tanpa spasi, dan pemisah berupa karakter khusus regex ditulis dengan kutip tunggal.

Nilai setelah -F diperlakukan sebagai ekspresi reguler, sehingga pemisah lain seperti tab dapat dituliskan dengan -F'\t'. Untuk berkas yang pemisahnya berupa spasi atau tab, opsi ini tidak diperlukan karena pemisah bawaan awk sudah mencakup keduanya. Pemilihan pemisah yang tepat menentukan isi $1, $2, dan seterusnya, sehingga keluaran yang tampak kosong biasanya berawal dari pemisah yang salah.

Medan terakhir dan banyak medan#

awk menyediakan dua nama khusus: NF berisi banyaknya medan pada baris yang sedang diproses, sedangkan $NF berisi isi medan terakhirnya. Bentuk $NF berguna apabila banyaknya kolom berubah-ubah tetapi kolom yang diinginkan selalu paling akhir.

bash
cd /tmp/kerja-awk
# mencetak medan terakhir dari setiap baris
awk '{print $NF}' nilai.txt
# mencetak banyaknya medan pada setiap baris
awk '{print NF}' nilai.txt
text Keluaran
78
85
92
81
74
2
2
2
2
2

Keluaran pertama menampilkan kolom nilai tanpa perlu tahu posisinya, sedangkan keluaran kedua menegaskan bahwa setiap baris memiliki dua medan. Perhatikan perbedaan penulisannya: NF tanpa tanda dolar adalah angka, sedangkan $NF dengan tanda dolar adalah isi medan pada posisi angka itu. Dua nama khusus ini biasanya dipakai bersama, misalnya $NF untuk mengambil kolom terakhir sebuah laporan yang jumlah kolomnya belum tentu tetap.

Menyaring baris dengan pola bersyarat#

Pola pada awk dapat berupa perbandingan, misalnya $2 >= 80. Aksi hanya dijalankan pada baris yang memenuhi perbandingan tersebut, sehingga perbandingan ini berfungsi seperti penyaring.

bash
cd /tmp/kerja-awk
# menampilkan nama pemilik nilai 80 ke atas
awk '$2 >= 80 {print $1}' nilai.txt
# menampilkan nama pemilik nilai di bawah 80
awk '$2 < 80 {print $1}' nilai.txt
text Keluaran
Budi
Citra
Dewi
Ali
Eko

Perbandingan ini bersifat numerik karena nilai yang dibandingkan berbentuk angka, sehingga 100 dianggap lebih besar daripada 20. Pola juga dapat berupa ekspresi reguler yang ditulis di antara dua garis miring, misalnya /^Ali/ untuk baris yang dimulai dengan Ali, dan beberapa pola dapat dituliskan berurutan dengan aksi masing-masing. Kombinasi pola bersyarat dengan print menghasilkan penyaringan sederhana terhadap berkas data tanpa perlu membuka editor apa pun.

One-liner perhitungan dengan END#

Blok tanpa pola dijalankan untuk setiap baris, sedangkan blok END dijalankan sekali setelah baris terakhir selesai diproses. Gabungan keduanya menghasilkan perhitungan akumulasi, misalnya total dan rata-rata kolom nilai. Variabel awk tidak perlu dideklarasikan dan bernilai 0 sebelum pertama kali dipakai. Variabel NR menyimpan nomor baris yang sedang diproses. Apabila lebih dari satu berkas diberikan, awk memperlakukan semuanya sebagai satu aliran masukan, sehingga NR melanjutkan hitungannya menembus batas berkas, sedangkan FNR menghitung ulang dari nol untuk tiap berkas.

bash
cd /tmp/kerja-awk
# menjumlahkan seluruh nilai
awk '{total += $2} END {print "total:", total}' nilai.txt
# menghitung rata-rata dengan NR sebagai banyaknya baris
awk '{total += $2} END {print "rata-rata:", total / NR}' nilai.txt
text Keluaran
total: 410
rata-rata: 82

Setelah semua baris selesai diproses, nilai NR menjadi banyaknya baris keseluruhan, sehingga total / NR pada perintah di atas menghasilkan rata-rata. Siklus hidup program awk yang lengkap mencakup blok BEGIN yang berjalan sebelum baris pertama dibaca, blok tanpa pola untuk setiap baris, dan blok END di akhir.

bash
cd /tmp/kerja-awk
# tiga jenis blok: BEGIN, per baris, lalu END
awk 'BEGIN {print "mulai"} {print $1} END {print "selesai"}' nilai.txt
text Keluaran
mulai
Ali
Budi
Citra
Dewi
Eko
selesai

Variabel NR juga dapat dipakai sebagai pola, misalnya untuk mengambil sebagian awal berkas.

bash
cd /tmp/kerja-awk
# menampilkan tiga baris pertama beserta nomornya
awk 'NR <= 3 {print NR, $0}' nilai.txt
text Keluaran
1 Ali 78
2 Budi 85
3 Citra 92

Kesalahan umum#

Kesalahan pertama adalah menulis program awk dengan tanda kutip ganda. Pada awk "{print $1}", shell menguraikan $1 sebagai argumen posisi shell yang kosong, sehingga program yang sampai ke awk menjadi {print } yang mencetak seluruh baris, bukan kolom pertamanya. Kutip tunggal '{print $1}' melindungi program dari shell.

Kesalahan kedua adalah lupa -F pada berkas berpemisah koma. Tanpa opsi itu, $1 berisi satu baris utuh dan $2 berisi teks kosong, sehingga hasilnya tampak hilang padahal yang salah adalah pemisahnya. Kesalahan ketiga adalah menganggap awk mengubah berkas. Sama seperti sed tanpa -i, awk hanya membaca masukan dan mencetak keluaran, sehingga berkas sumbernya tidak pernah berubah.

Ringkasan#

  • awk memproses teks baris demi baris dengan model pola { aksi }, dan setiap baris terbagi menjadi medan $1, $2, dan seterusnya, sementara $0 berisi baris utuh.
  • Opsi -F mengatur pemisah medan, NF menyimpan banyaknya medan, dan $NF mengambil isi medan terakhir.
  • Pola berupa perbandingan seperti $2 >= 80 menyaring baris secara numerik sebelum aksinya dijalankan.
  • Blok END berjalan sekali setelah semua baris, sehingga bersama akumulasi variabel menghasilkan one-liner total dan rata-rata, dengan NR sebagai penghitung baris.

Referensi#