Bab 3 membekali kita dengan variabel yang menyimpan satu nilai tunggal, entah itu string atau angka. Kebutuhan nyata jarang sesederhana itu: daftar nama file yang perlu di-backup, daftar user yang perlu dicek statusnya, atau daftar port yang perlu dipantau, semuanya adalah kumpulan nilai yang idealnya disimpan dalam satu wadah, bukan dipecah ke puluhan variabel terpisah bernama file1, file2, file3, dan seterusnya. Di sinilah array berperan. Bab ini membahas dua jenis array yang didukung Bash, yaitu indexed array yang mengurutkan elemen berdasarkan angka dan associative array yang memakai key berupa teks, dilanjutkan dengan operasi umum seperti menambah, menghapus, dan slicing elemen, dan ditutup dengan studi kasus mengolah data terstruktur sederhana yang relevan baik untuk User maupun Sysadmin.
4.1 Indexed Array: Deklarasi dan Akses Elemen
Sub-bab ini membahas jenis array paling dasar dan paling sering dipakai di Bash: indexed array. Hampir semua contoh array yang muncul di bab-bab berikutnya, termasuk saat memproses argumen script di Bab 12 dan memproses banyak file sekaligus di Bab 7, memakai jenis array ini.
4.1.1 Apa itu Indexed Array?
Indexed array adalah array yang setiap elemennya diberi label berupa angka index berurutan, dimulai dari angka nol. Cara kerjanya mirip rak bernomor: elemen pertama menempati nomor 0, elemen kedua nomor 1, dan seterusnya. Berbeda dari bahasa pemrograman seperti C atau Java, index di Bash tidak wajib berurutan tanpa celah. Kita bisa saja hanya mengisi index 0 dan index 5, dan Bash tetap menganggapnya sebagai satu array yang sah, kondisi yang disebut sparse array. Karakteristik ini penting diingat karena akan berpengaruh saat membahas penghapusan elemen di sub-bab 4.3.2.
4.1.2 Membuat Array dengan Assignment
Cara paling umum membuat indexed array adalah lewat compound assignment, yaitu menuliskan semua elemen di dalam tanda kurung, dipisahkan spasi.
buah=("apel" "jeruk" "mangga")Bash tidak mengharuskan deklarasi tipe lebih dulu seperti declare -a, cukup assignment di atas sudah otomatis membuat buah dikenali sebagai indexed array. Menambahkan declare -a sebelum assignment tetap valid dan kadang dipakai untuk mempertegas maksud kode, terutama di script yang lebih besar.
declare -a buah
buah=("apel" "jeruk" "mangga")Selain compound assignment, elemen juga bisa diisi satu per satu lewat index eksplisit, termasuk mengisi index yang melompat sehingga sengaja membuat array menjadi sparse.
warna[0]="merah"
warna[1]="hijau"
warna[5]="biru"4.1.3 Mengakses Elemen Array
Untuk membaca satu elemen, sebutkan nama array diikuti index di dalam tanda kurung siku, dibungkus ${ }.
echo "${buah[0]}"Baris di atas menampilkan apel, karena index 0 merujuk elemen pertama. Untuk mengambil seluruh elemen sekaligus, pakai ${buah[@]} atau ${buah[*]}. Keduanya terlihat sama saat ditampilkan begitu saja, tapi punya perbedaan penting saat dibungkus double quote: "${buah[@]}" memperlakukan setiap elemen sebagai kata terpisah (mempertahankan batas antar elemen meski ada spasi di dalamnya), sementara "${buah[*]}" menggabungkan seluruh elemen menjadi satu string tunggal yang dipisahkan karakter pertama dari IFS (spasi secara default).
echo "${buah[@]}"
echo "${buah[*]}"Perbedaan ini akan terasa dampaknya saat array dipakai di dalam for loop pada sub-bab berikutnya: bentuk "${buah[@]}" adalah pilihan yang benar hampir di semua kasus, sejalan dengan prinsip quoting yang sudah dibahas di Bab 3.
4.1.4 Iterasi Elemen dengan for Loop
Pola paling umum memproses seluruh elemen array adalah lewat for loop. Sintaks lengkap for loop akan dibahas tuntas di Bab 7, tapi pola dasarnya sudah bisa dipakai sejak sekarang.
for item in "${buah[@]}"; do
echo "Buah: $item"
doneJika yang dibutuhkan bukan hanya nilai tapi juga index-nya, gunakan ${!buah[@]}, yaitu tanda seru sebelum nama array yang membuat Bash mengembalikan daftar index (atau key, untuk associative array di sub-bab 4.2) alih-alih nilainya.
for i in "${!buah[@]}"; do
echo "Index $i berisi ${buah[$i]}"
donePola ${!buah[@]} ini juga yang membuat iterasi tetap aman dilakukan meski array bersifat sparse, karena Bash hanya mengembalikan index yang benar-benar terisi, bukan mengasumsikan rentang 0 sampai jumlah elemen dikurangi satu secara berurutan.
4.1.5 Verifikasi dan Troubleshooting Indexed Array
Cara cepat memeriksa isi lengkap sebuah array beserta atributnya adalah lewat declare -p, builtin yang sama seperti dipakai untuk variabel biasa di Bab 3.
declare -p buahdeclare -a buah=([0]="apel" [1]="jeruk" [2]="mangga")Kesalahan yang cukup sering ditemui pemula adalah lupa membungkus ${buah[@]} dengan double quote, sehingga elemen yang mengandung spasi ikut terpecah menjadi beberapa kata, persis masalah word splitting yang sudah dibahas di Bab 3. Kesalahan lain yang lebih halus adalah mengakses index yang tidak pernah diisi. Bash tidak menampilkan error, cukup mengembalikan string kosong.
echo "Index 10: ${buah[10]}"Baris di atas hanya menampilkan Index 10: tanpa error apa pun, karena index 10 memang belum pernah diisi. Perilaku "diam saja" ini mirip dengan memanggil variabel biasa yang belum dideklarasikan seperti dibahas di Bab 3, dan baru bisa diubah menjadi error eksplisit lewat opsi set -u yang akan dibahas di Bab 25.
4.2 Associative Array dengan declare -A
Setelah memahami indexed array, sub-bab ini membahas jenis array kedua yang justru lebih cocok dipakai saat data yang disimpan punya makna lebih jelas lewat nama daripada lewat urutan angka, misalnya memetakan nama server ke alamat IP-nya atau nama konfigurasi ke nilainya.
4.2.1 Apa itu Associative Array?
Associative array adalah array yang memakai teks bebas, disebut key, sebagai penunjuk setiap elemen, bukan angka index berurutan seperti indexed array di sub-bab 4.1. Strukturnya berupa pasangan key-value: setiap key yang unik menyimpan satu value. Fitur ini baru tersedia mulai Bash versi 4.0 ke atas, berbeda dari indexed array yang sudah ada sejak versi Bash yang jauh lebih lama. Ini poin penting untuk diperhatikan, karena seperti sudah disinggung di Bab 1, macOS masih membawa Bash bawaan versi 3.2 karena alasan lisensi, sehingga associative array tidak akan berfungsi kecuali Bash diperbarui lewat Homebrew.
4.2.2 Deklarasi dengan declare -A
Berbeda dari indexed array yang bisa langsung dipakai tanpa deklarasi eksplisit, associative array wajib dideklarasikan lebih dulu dengan declare -A sebelum diisi.
declare -A user_info
user_info["nama"]="Budi"
user_info["role"]="sysadmin"Sama seperti indexed array, associative array juga bisa langsung diisi lewat compound assignment dalam satu baris, dengan setiap pasangan key-value ditulis di dalam tanda kurung siku.
declare -A server=(
["web1"]="192.168.1.10"
["db1"]="192.168.1.20"
)4.2.3 Mengakses dan Mengubah Value
Mengambil value dari sebuah key mengikuti sintaks yang sama seperti indexed array, hanya saja isi kurung siku berupa key bertipe string, bukan angka index.
echo "${server["web1"]}"Untuk mengubah value dari key yang sudah ada, cukup lakukan assignment ulang ke key yang sama. Bash otomatis menimpa value lama dengan yang baru, tanpa perlu menghapusnya lebih dulu.
server["web1"]="192.168.1.99"4.2.4 Iterasi Key dan Value
Sama seperti pola ${!buah[@]} pada indexed array di sub-bab 4.1.4, tanda seru di depan nama associative array mengembalikan seluruh key yang tersimpan, yang kemudian bisa dipakai untuk mengambil value masing-masing.
for key in "${!server[@]}"; do
echo "$key -> ${server[$key]}"
doneSatu perbedaan penting dibanding indexed array: urutan key yang dihasilkan ${!server[@]} tidak dijamin mengikuti urutan saat data dimasukkan, karena associative array di Bash disimpan dalam struktur hash, bukan struktur berurutan seperti indexed array. Jika urutan tampilan penting, sortir daftar key lebih dulu sebelum iterasi, misalnya dengan menyalurkannya ke sort, topik yang akan lebih banyak disinggung saat membahas pipe di Bab 5.
4.2.5 Troubleshooting: Associative Array Butuh Bash 4+
Kesalahan paling umum saat baru belajar associative array adalah langsung mengisi key tanpa declare -A lebih dulu.
server["web1"]="192.168.1.10"Tanpa declare -A, Bash memperlakukan server sebagai indexed array biasa, dan isi di dalam kurung siku ("web1") dievaluasi sebagai ekspresi aritmatika, bukan sebagai teks. Karena web1 bukan variabel numerik yang valid, Bash menganggapnya bernilai 0, sehingga value di atas justru tersimpan di index 0, bukan di key "web1" seperti yang dimaksud. Kesalahan ini sering luput karena tidak memicu error, hanya membuat data tersimpan di tempat yang salah.
Kesalahan kedua yang lebih jelas errornya adalah menjalankan declare -A di Bash versi lama.
declare -A server
bash: declare: -A: invalid optionJika pesan error ini muncul, periksa versi Bash yang aktif lebih dulu sebelum menelusuri kemungkinan lain.
bash --version
echo "$BASH_VERSION"Di lapangan, kasus ini paling sering ditemui saat script yang dikembangkan di Linux dijalankan di macOS tanpa memastikan PATH mengarah ke Bash versi baru dari Homebrew lebih dulu, sesuai langkah yang sudah dibahas di Bab 1 dan catatan versi di sub-bab 4.2.1.
| Aspek | Indexed Array | Associative Array |
|---|---|---|
| Penunjuk elemen | Angka index, mulai dari 0 | Key berupa teks bebas |
| Urutan elemen | Terjamin sesuai urutan index | Tidak terjamin (struktur hash) |
| Perlu deklarasi eksplisit | Tidak wajib (declare -a opsional) | Wajib (declare -A) |
| Ketersediaan versi Bash | Sejak versi lama | Bash 4.0 ke atas |
4.3 Operasi Umum pada Array
Setelah menguasai deklarasi dan iterasi dasar, sub-bab ini membahas operasi yang paling sering dipakai sehari-hari saat bekerja dengan array: menambah elemen baru, menghapus elemen yang tidak dibutuhkan, mengambil sebagian elemen lewat slicing, dan menghitung jumlah elemennya.
4.3.1 Menambah Elemen dengan Operator +=
Untuk menambah elemen baru ke indexed array tanpa menimpa isi yang sudah ada, gunakan operator += diikuti elemen baru di dalam tanda kurung.
buah+=("nanas")Elemen baru otomatis ditempatkan setelah index tertinggi yang sudah ada. Operator yang sama juga berlaku untuk associative array, hanya saja formatnya berupa pasangan key-value baru, dan bisa menambahkan lebih dari satu pasangan sekaligus dalam satu baris.
server+=(["cache1"]="192.168.1.30" ["cache2"]="192.168.1.31")4.3.2 Menghapus Elemen dengan unset
Builtin unset yang sudah dipakai untuk menghapus variabel biasa di Bab 3 juga berlaku untuk menghapus satu elemen array, cukup sebutkan index atau key-nya.
unset 'buah[1]'Penting dipahami, menghapus satu elemen indexed array tidak membuat Bash otomatis menyusun ulang (reindex) index yang tersisa. Array yang tadinya rapat justru menjadi sparse, persis konsep yang sudah disinggung di sub-bab 4.1.1.
buah=("apel" "jeruk" "mangga")
unset 'buah[1]'
declare -p buahdeclare -a buah=([0]="apel" [2]="mangga")Perhatikan index 1 hilang sepenuhnya dari output declare -p, bukan berubah menjadi string kosong. Untuk menghapus seluruh isi array sekaligus beserta variabelnya, panggil unset tanpa index.
unset buah4.3.3 Slicing Array
Slicing adalah teknik mengambil sebagian elemen array berdasarkan posisi awal dan jumlah elemen yang diinginkan, memakai sintaks ${array[@]:offset:length}.
angka=(10 20 30 40 50)
echo "${angka[@]:1:3}"Baris di atas menghasilkan 20 30 40, karena slicing dimulai dari offset 1 (elemen kedua) dan mengambil sebanyak 3 elemen. Parameter length boleh dihilangkan jika ingin mengambil semua elemen mulai dari offset tertentu sampai akhir array.
echo "${angka[@]:2}"Bash juga mendukung offset negatif untuk mengambil elemen dihitung mundur dari akhir array. Satu detail teknis yang wajib diperhatikan: offset negatif harus dipisahkan spasi dari tanda titik dua sebelumnya, karena tanpa spasi Bash justru menafsirkannya sebagai sintaks ${parameter:-default} yang berbeda arti sepenuhnya.
echo "${angka[@]: -2}"Baris di atas mengambil 2 elemen terakhir, yaitu 40 50. Sebagai catatan tambahan, Bash versi 4.3 ke atas juga mendukung indeks negatif langsung pada indexed array, misalnya ${angka[-1]} untuk mengambil elemen terakhir tanpa perlu menghitung panjang array lebih dulu.
4.3.4 Menghitung Panjang Array
Jumlah elemen sebuah array didapat lewat ${#array[@]}, tanda pagar di depan nama array yang dikombinasikan dengan subscript @ atau *.
buah=("apel" "jeruk" "mangga")
echo "Jumlah buah: ${#buah[@]}"Perlu hati-hati membedakan sintaks ini dengan ${#buah[0]} yang justru menghitung panjang karakter dari string di index 0, bukan jumlah elemen array. Dua sintaks yang mirip ini punya makna sama sekali berbeda dan cukup sering tertukar oleh pemula.
echo "Panjang elemen pertama: ${#buah[0]}"Untuk array yang sudah pernah kehilangan elemen lewat unset seperti dibahas di sub-bab 4.3.2, ${#buah[@]} tetap akurat menghitung jumlah elemen yang benar-benar tersisa, bukan menghitung berdasarkan index tertinggi yang pernah ada.
4.3.5 Troubleshooting: Sparse Array Setelah unset
Kebiasaan yang berbahaya, dan cukup sering ditemui di script buatan pemula, adalah mengasumsikan index array selalu berurutan rapat dari 0 sampai jumlah_elemen - 1, lalu memakai asumsi itu untuk iterasi manual dengan for loop bergaya C.
buah=("apel" "jeruk" "mangga")
unset 'buah[1]'
for (( i=0; i<${#buah[@]}; i++ )); do
echo "${buah[$i]}"
doneKarena ${#buah[@]} sekarang bernilai 2 (bukan 3, sesuai penjelasan di sub-bab 4.3.4), loop hanya berjalan untuk i=0 dan i=1. Padahal elemen yang tersisa sebenarnya ada di index 0 dan index 2, sehingga mangga di index 2 justru tidak pernah tercetak, dan i=1 mencetak string kosong karena index tersebut sudah dihapus. Pelajaran dari kasus ini: setelah sebuah array pernah mengalami unset pada elemen tertentu, selalu iterasi memakai pola "${buah[@]}" atau "${!buah[@]}" seperti dibahas di sub-bab 4.1.4, jangan mengandalkan asumsi index berurutan rapat.
4.4 Studi Kasus: Mengolah Data Terstruktur
Sub-bab penutup ini menggabungkan indexed array dan associative array dalam satu skenario praktis: memverifikasi keberadaan sekumpulan direktori penting di server sekaligus menampilkan prioritas backup masing-masing, sebuah tugas nyata yang biasa dikerjakan Sysadmin sebelum menjadwalkan backup otomatis, topik yang akan dibahas lebih lengkap di Bab 21.
4.4.1 Skenario dan Rancangan Data
Anggap ada tiga direktori konfigurasi penting di sebuah server yang perlu dipastikan keberadaannya: direktori konfigurasi nginx, direktori data mysql, dan direktori root aplikasi web. Setiap direktori juga punya tingkat prioritas backup yang berbeda. Kebutuhan ini pas dipetakan dengan dua array sekaligus: indexed array untuk menyimpan daftar path yang perlu dicek satu per satu secara berurutan, dan associative array untuk memetakan setiap path ke prioritas backup-nya.
4.4.2 Menulis Script Lengkap
Simpan script berikut, gabungan dari seluruh teknik array yang sudah dibahas di sub-bab 4.1 sampai 4.3, ditambah struktur kondisi if yang akan dibahas lebih detail di Bab 6.
#!/bin/bash
direktori_penting=(
"/etc/nginx"
"/etc/mysql"
"/var/www/html"
)
declare -A prioritas_backup=(
["/etc/nginx"]="tinggi"
["/etc/mysql"]="tinggi"
["/var/www/html"]="sedang"
)
echo "Total direktori yang diperiksa: ${#direktori_penting[@]}"
echo "---"
for dir in "${direktori_penting[@]}"; do
if [ -d "$dir" ]; then
status="ada"
else
status="tidak ditemukan"
fi
echo "$dir -> status: $status, prioritas: ${prioritas_backup[$dir]}"
done4.4.3 Verifikasi Output dan Pengembangan Lanjutan
Jalankan script setelah diberi izin eksekusi, sesuai kebiasaan yang sudah dibahas di Bab 1.
chmod +x cek_direktori.sh
./cek_direktori.shPada server dengan nginx dan mysql terpasang tapi direktori /var/www/html belum pernah dibuat, output yang dihasilkan kurang lebih seperti berikut.
Total direktori yang diperiksa: 3
---
/etc/nginx -> status: ada, prioritas: tinggi
/etc/mysql -> status: ada, prioritas: tinggi
/var/www/html -> status: tidak ditemukan, prioritas: sedangScript ini bisa dikembangkan lebih jauh, misalnya menambah direktori baru ke direktori_penting lewat operator += dari sub-bab 4.3.1 tanpa perlu mengubah logika loop sama sekali, karena loop sudah dirancang mengikuti isi array secara dinamis, bukan angka yang di-hardcode. Prinsip inilah yang menjadi keunggulan utama array dibanding menulis variabel terpisah satu per satu seperti disinggung di awal bab ini: menambah data baru cukup dengan menambah satu baris, tanpa menyentuh logika pemrosesannya. Kombinasi indexed array dan associative array seperti pada studi kasus ini akan dipakai kembali dalam bentuk yang lebih kompleks saat membahas parsing argumen script di Bab 12 dan script audit kondisi server di Bab 17.

