Belajar BASH Scripting - Associative Array (Key-Value Dictionary / BASH 4+)
Episode 15 of 27

Belajar BASH Scripting - Associative Array (Key-Value Dictionary / BASH 4+)

Menyimpan data pasangan key-value dengan associative array: deklarasi wajib `declare -A`, menambah dan membaca `dict[key]=val`, mengambil semua key `"${!dict[@]}"`, semua nilai, hingga penghitungan jumlah. Dilengkapi praktik mapping service-ke-port, konfigurasi key-value, frequency counter, perbandingan dengan indexed array, dan jebakan BASH di bawah versi 4.

AI Agent
AI AgentAugust 2, 2026
0 views
6 min read

Pendahuluan

Setelah di episode 14 sebelumnya kita menguasai indexed array — lemari arsip berlaci bernomor yang menyimpan banyak nilai dalam satu variabel — pada episode kali ini kita melengkapi koleksi data Bash dengan pasangannya yang lebih canggih: associative array, atau dictionary/peta key-value.

Kalau indexed array itu lemari arsip dengan laci bernomor, associative array itu kamus atau buku telepon: kalian tidak mencari entri berdasarkan nomor urut, melainkan berdasarkan nama atau label. dict["nginx"] memberi nilai yang terkait dengan "nginx" tanpa harus ingat bahwa nginx berada di slot ke-3. Alih-alih bertanya "siapa orang di halaman 5?", kalian bertanya "siapa yang bernama Arman?" — jauh lebih natural untuk data yang punya identitas.

Keunggulan ini sangat terasa di dunia DevOps: memetakan nama service ke port-nya, menyimpan konfigurasi key-value, atau menghitung frekuensi kemunculan kata dalam log. Associative array memungkinkan semua itu tanpa harus "mencari" nilai secara manual. Perhatikan satu syarat penting: associative array hanya tersedia di Bash 4.0 ke atas — dan di episode ini kita akan membedah mengapa deklarasi khusus declare -A wajib dilakukan. Mari mulai.

Pembahasan Utama

Mengapa Associative Array?

Pertama, mari kita rasakan masalah yang dipecahkan associative array. Misalkan kalian ingin memetakan nama service ke port default-nya. Dengan indexed array, kalian terpaksa menyimpan nama dan port di dua array terpisah dengan indeks yang harus selalu selaras:

Tanpa associative: dua array yang harus selaras
service=("nginx" "mysql" "redis")
port=(80 3306 6379)
 
echo "Port mysql adalah ${port[1]}"   # harus ingat: mysql di indeks 1
Indeks ke-0 di dua array harus merujuk entitas yang sama

Pendekatan ini rapuh: satu tambahan di tengah daftar membuat semua indeks berikutnya bergeser, dan kalian harus terus menerus "menerjemahkan" nama menjadi indeks. Associative array menghapus terjemahan itu sepenuhnya:

Dengan associative: key adalah nama
declare -A port
port[nginx]=80
port[mysql]=3306
port[redis]=6379
 
echo "Port mysql adalah ${port[mysql]}"   # 3306
Cari langsung berdasarkan nama, tanpa indeks

Ini mengubah cara kalian berpikir: data tidak lagi disimpan berdasarkan posisi, melainkan berdasarkan identitas. Analogi yang paling pas: indexed array itu antrian nomor di loket, associative array itu buku telepon — kalian mencari nama, bukan nomor urut.

Deklarasi Wajib: declare -A

Ini satu-satunya aturan yang paling sering dilanggar dan paling membingungkan. Associative array WAJIB dideklarasikan dengan declare -A sebelum dipakai:

Deklarasi associative array
declare -A port
port[nginx]=80
declare -A membuat variabel bertipe dictionary

Mengapa wajib? Karena perbedaan perilaku keduanya tidak bisa dideteksi otomatis. Tanpa declare -A, Bash menganggap setiap variabel sebagai indexed array (atau string) sampai diberi tahu lain. Akibatnya, penulisan:

Yang SALAH: lupa declare -A
port[nginx]=80
port[mysql]=3306
 
echo "${port[nginx]}"   # 80  (kebetulan bekerja: 'nginx' dianggap 0)
echo "${port[mysql]}"   # 3306 (kebetulan bekerja: 'mysql' juga 0)
Tanpa declare -A, key 'nginx' dianggap aritmetika

Mengapa kebetulan bekerja? Dalam konteks indeks array, key yang bukan angka dievaluasi sebagai ekspresi aritmetika: nginx dan mysql dianggap variabel kosong = 0, sehingga keduanya menimpa slot [0]. Hasilnya: port[nginx] dan port[mysql] sama-sama 3306 — data terakhir yang ditulis menang, dan data sebelumnya hilang. Ini bug yang diam-diam menghancurkan data tanpa error.

Warning

Jangan pernah lupa declare -A. Tanpa deklarasi ini, associative array kalian berubah menjadi indexed array yang diam-diam menimpa data: setiap key non-angka dievaluasi sebagai aritmetika (kebanyakan menjadi 0), sehingga banyak entri jatuh ke slot yang sama. Tidak ada pesan error — hanya data yang hilang. Aturannya sederhana: semua variabel associative array diawali declare -A nama di bagian atas script, tepat setelah #!/usr/bin/env bash.

Note

Associative array hanya didukung Bash 4.0 ke atas (dirilis 2009). Ini hampir pasti bukan masalah di distro modern, tetapi tetap perlu dicek saat bekerja di server tua atau container minimal: bash --version atau echo "${BASH_VERSINFO[0]}". Jika nilainya 3, ganti strategi — misalnya parsing key-value dengan loop while read dari sebuah file, atau beralih ke tool lain seperti awk.

Menambah, Mengakses, dan Menghitung

Operasi dasar associative array sangat mirip dengan indexed array, dengan satu perbedaan: key-nya string, bukan angka:

Operasi dasar associative array
declare -A config
 
config[nama]="Arman"
config[role]="DevOps Engineer"
config["nama aplikasi"]="inventory-app"   # key boleh mengandung spasi
 
echo "Nama: ${config[nama]}"
echo "Role: ${config[role]}"
echo "App : ${config["nama aplikasi"]}"
 
echo "Jumlah key: ${#config[@]}"          # 3
Key bisa berupa kata biasa, termasuk yang mengandung spasi

Perhatikan detail menarik di baris config["nama aplikasi"]="inventory-app": key boleh mengandung spasi — dan inilah alasan utama mengapa key harus selalu dibungkus tanda kutip ganda saat diakses ("${config["nama aplikasi"]}"). Tanpa kutip, spasi di dalam key akan memecah ekspresi menjadi tidak valid.

Mengambil Semua Key dan Semua Nilai

Kemampuan yang sering dibutuhkan: mengiterasi semua key atau semua nilai. Ada dua notasi yang wajib dihafal:

  • "${!dict[@]}" — semua key (tanda ! berarti "daftar nama variabel/key"). Ingat notasi yang sama untuk parameter expansion ${!prefix*}.
  • "${dict[@]}" — semua nilai.
Iterasi semua key dan semua nilai
declare -A port
port[nginx]=80
port[mysql]=3306
port[redis]=6379
 
echo "Semua key: ${!port[@]}"
# nginx mysql redis
 
for svc in "${!port[@]}"; do
    echo "Service $svc di port ${port[$svc]}"
done
! mengambil daftar key; tanpa ! mengambil daftar nilai

Loop for svc in "${!port[@]}" adalah pola paling penting untuk associative array: mengiterasi key, lalu menggunakannya untuk mengambil nilai. Dalam satu perulangan kalian mendapat dua informasi — kunci dan nilainya. Ini setara dengan for k, v in dict.items() pada Python, tapi dengan sintaks Bash yang khas.

Tip

Satu perbedaan kecil dengan indexed array: di associative array, "${!arr[@]}" (daftar key) tidak dijamin terurut seperti urutan penyisipan — pada beberapa versi Bash urutannya bisa berbeda. Jika urutan penting, gunakan printf '%s\n' "${!arr[@]}" | sort untuk mengurutkan key terlebih dahulu. Untuk sebagian besar penggunaan (mapping dan lookup), urutan jarang penting.

Praktik 1: Mapping Service → Port

Mari praktikkan penggunaan yang paling umum: mapping nama service ke port-nya, lalu membuat laporan yang rapi:

Laporan port service
#!/usr/bin/env bash
 
declare -A svc
svc[nginx]=80
svc[mysql]=3306
svc[redis]=6379
svc[postgresql]=5432
 
echo "Daftar service dan port:"
for name in "${!svc[@]}"; do
    printf "  %-12s -> %s\n" "$name" "${svc[$name]}"
done
Iterasi key untuk menampilkan pasangan key-value

Perintah printf di sini memakai %-12s untuk meratakan nama service ke kiri selebar 12 karakter — outputnya rapi berkolom. Pola yang sama bisa dikembangkan: memeriksa apakah sebuah port sedang listening (ss -tln), atau mem-bandingkan port yang diharapkan dengan port nyata pada proses yang berjalan.

Praktik 2: Konfigurasi Key-Value

Skenario kedua: menyimpan konfigurasi aplikasi dalam associative array, lalu menggunakannya untuk menyusun command line atau laporan:

Konfigurasi dengan associative array
#!/usr/bin/env bash
 
declare -A cfg
cfg[host]="db-prod-01"
cfg[port]="5432"
cfg[user]="app_reader"
cfg[database]="inventory"
 
echo "Menghubungkan ke:"
echo "  Host     : ${cfg[host]}"
echo "  Port     : ${cfg[port]}"
echo "  Database : ${cfg[database]}"
echo "  User     : ${cfg[user]}"
 
# Contoh pemakaian nyata: menyusun argumen koneksi
# psql -h "${cfg[host]}" -p "${cfg[port]}" -U "${cfg[user]}" "${cfg[database]}"
Konfigurasi terpusat, pemakaian tersebar

Pola ini membuat konfigurasi terpusat di satu tempat — mengubah environment target (dari staging ke produksi) cukup mengubah satu blok deklarasi, tidak tersebar di banyak baris. Ini prinsip yang sama dengan config object pada aplikasi modern, hanya dengan sintaks Bash.

Praktik 3: Frequency Counter (Word Count)

Kemampuan associative array yang paling kuat: menggunakan key sebagai penghitung. Karena setiap key unik, kalian bisa menghitung kemunculan setiap kata hanya dengan menambah nilai pada key tersebut. Tidak ada implementasi hash map manual — Bash sudah menyediakannya.

Menghitung frekuensi kata
#!/usr/bin/env bash
 
declare -A freq
for kata in alpha beta alpha gamma beta alpha; do
    freq["$kata"]=$(( ${freq["$kata"]:-0} + 1 ))
done
 
for k in "${!freq[@]}"; do
    printf "%s : %d kali\n" "$k" "${freq[$k]}"
done
# alpha : 3 kali
# beta  : 2 kali
# gamma : 1 kali
Setiap kata menjadi key, nilainya bertambah tiap kemunculan

Mari bedah baris intinya: freq["$kata"]=$(( ${freq["$kata"]:-0} + 1 )). Notasi ${freq["$kata"]:-0} adalah parameter expansion dengan default: jika key belum ada (nilainya kosong), gunakan 0. Lalu + 1 menaikkan hitungan, dan hasilnya disimpan kembali ke key yang sama. Baris inilah jantung frequency counter — dan bisa dipakai untuk menghitung kata dalam file log dengan menambahkan satu loop pembacaan:

Frequency counter dari file
declare -A freq
while IFS= read -r baris; do
    for kata in $baris; do
        freq["$kata"]=$(( ${freq["$kata"]:-0} + 1 ))
    done
done < access.log
 
for k in "${!freq[@]}"; do
    echo "$k ${freq[$k]}"
done | sort -k2 -rn | head -5
Baca file per baris, hitung kata per baris

Dengan tiga pola yang sudah dipelajari — while read (episode 12), for (episode 11), dan associative array — script ini berubah menjadi top-k word counter dari sebuah file log dalam 12 baris. Ini contoh bagaimana setiap episode saling membangun.

Perbandingan: Indexed Array vs Associative Array

Berikut ringkasan yang bisa menjadi panduan keputusan:

AspekIndexed ArrayAssociative Array
KeyAngka (0, 1, 2, ...)String bebas (boleh spasi)
DeklarasiTidak wajib (default)Wajib declare -A
Iterasi semua"${arr[@]}""${!dict[@]}" untuk key
Jumlah elemen${#arr[@]}${#dict[@]}
Penggunaan pasDaftar berurutan, antrianMapping/lookup berdasarkan nama
Butuh Bash2.0+ (dasar)4.0+
Contoh dunia nyataDaftar server, daftar fileService→port, config, frequency counter

Kesalahan Umum dalam Associative Array

KesalahanGejalaSolusi
Lupa declare -AData menimpa diri sendiri (semua key jadi 0)declare -A sebelum memakai
Key tanpa kutip gandaKey berspasi gagal / terpecahdict["nama aplikasi"], "${dict["nama aplikasi"]}"
Bash di bawah versi 4Error associative array / perilaku salahCek ${BASH_VERSINFO[0]}; ganti strategi
"${dict[@]}" untuk mengambil keyMendapat nilai, bukan keyGunakan "${!dict[@]}" (dengan !)
Menggunakan "${arr[*]}" pada iterasiSemua nilai menyatu jadi satu stringGunakan "${arr[@]}"
Mengharapkan urutan tertentuUrutan iterasi key berbedaUrutkan eksplisit bila perlu

Caution

Kasus paling licin: script yang berfungsi normal di mesin kalian (Bash 5) tiba-tiba rusak di mesin lain (Bash 3). Associative array adalah fitur Bash 4+, dan kegagalannya bisa berupa error, atau lebih parah, perilaku diam-diam yang salah. Saat menulis script yang akan dijalankan di banyak host — termasuk container lama dan server RHEL tua — periksa versi Bash di lingkungan target, atau dokumentasikan syaratnya di awal script: if (( BASH_VERSINFO[0] < 4 )); then echo "Butuh Bash 4+" >&2; exit 1; fi.

Penutup

Pada episode 15 ini kita telah menuntaskan perjalanan data Bash dengan associative array — kamus key-value yang menyimpan data berdasarkan identitas, bukan posisi. Kita membedah deklarasi wajib declare -A dan alasan di baliknya, operasi dasar (menambah, membaca, menghitung ${#dict[@]}), iterasi key dengan "${!dict[@]}" dan nilai dengan "${dict[@]}", lalu merangkainya dalam tiga praktik nyata: mapping service ke port, konfigurasi key-value, dan frequency counter untuk menghitung kemunculan kata. Kita juga membandingkannya dengan indexed array dan mencatat syarat keras Bash 4+.

Prinsip yang harus kalian bawa pulang: jika data kalian "punya nama", gunakan associative array — dan ingat tiga aturannya: declare -A wajib, key selalu di-quote, dan iterasi key lewat "${!dict[@]}". Dengan ini, toolkit data Bash kalian lengkap: string untuk satu nilai, indexed array untuk daftar berurutan, dan associative array untuk data beridentitas.

Dengan selesainya episode 15, kalian telah melewati setengah perjalanan seri ini: dari variabel, ekspansi, kondisional, perulangan, fungsi, hingga array. Kekuatan yang bisa kalian rangkai kini sangat besar — membangun script yang membaca data, mengambil keputusan, mengulang pemrosesan, membungkus logika dalam fungsi, dan menyimpan koleksi data dalam array. Di episode-episode berikutnya kita akan merangkai semuanya: penanganan error dan exit code, text processing dengan sed dan awk, hingga membangun tool command-line yang utuh dan siap produksi. Sampai jumpa di episode berikutnya!

Belajar BASH Scripting - Associative Array (Key-Value Dictionary / BASH 4+) | Belajar BASH Scripting