Menyimpan banyak nilai dalam satu variabel dengan indexed array: deklarasi, akses per indeks, iterasi seluruh elemen dengan `"${arr[@]}"`, penghitungan jumlah, append, pemotongan (slice), hingga penghapusan elemen. Dilengkapi praktik daftar server untuk ping dan daftar file backup beserta jebakan yang sering menjebak.

Setelah di episode 13 sebelumnya kita belajar membungkus logika menjadi functions — blok kode bernama yang bisa dipanggil ulang — pada episode kali ini kita membahas satu hal yang membuat fungsi dan perulangan semakin bertenaga: menyimpan banyak nilai dalam satu variabel melalui indexed array.
Sejauh ini, satu variabel hanya bisa menyimpan satu nilai: user="arman". Bagaimana jika kalian perlu menyimpan daftar 20 server, daftar 50 file backup, atau 100 angka hasil perhitungan? Membuat 20 variabel terpisah (server1, server2, ...) itu tidak masuk akal — dan itulah masalah yang dipecahkan array.
Bayangkan lemari arsip dengan laci bernomor. Setiap laci menyimpan satu dokumen, dan nomor lacinya adalah kunci untuk mengambilnya. Array persis seperti itu: satu nama (arr), banyak slot yang diindeks angka (arr[0], arr[1], ...). Alih-alih membawa 20 map terpisah di tangan, kalian membawa satu lemari — jauh lebih mudah dipindahkan dan diproses.
Kombinasi array + perulangan for (episode 11) adalah salah satu kombinasi paling produktif dalam scripting: array menyimpan data, loop memprosesnya. Pada episode ini kita akan menguasai semua operasi dasar array — deklarasi, akses, iterasi, append, slice, dan unset — lalu merangkainya dalam dua praktik nyata: memantau daftar server dan mem-backup daftar file.
Sebelum sintaks, mari kita tegaskan masalah yang dipecahkan array. Perhatikan pendekatan tanpa array untuk mengelola beberapa server:
server1="web-01"
server2="web-02"
server3="db-01"
echo "$server1"
echo "$server2"
echo "$server3"Pendekatan ini rusak dengan cepat: tidak ada cara mudah untuk mengiterasi variabel-variabel itu, menghitung berapa jumlahnya, atau menambahkan yang baru tanpa menulis kode baru. Dengan array, semua daftar itu menjadi satu entitas yang bisa dihitung, diulang, dan diperpanjang secara dinamis. Inilah yang disebut data-driven scripting: script tidak lagi mengkode-keras setiap item, melainkan memproses seluruh koleksi dengan satu perintah.
Array di Bash dideklarasikan dengan tanda kurung dan elemen dipisahkan spasi:
buah=("apel" "mangga" "pisang")
echo "${buah[0]}"
echo "${buah[1]}"
echo "${buah[2]}"
# apel
# mangga
# pisangAda dua hal yang wajib kalian perhatikan dalam sintaks akses:
0. Elemen pertama adalah arr[0], bukan arr[1]. Ini konvensi universal yang sama dengan bahasa C dan hampir semua bahasa modern.{} wajib saat akses. ${buah[0]} — tanpa kurung kurawal, Bash akan keliru membaca buah[0] sebagai nama variabel aneh. Kurung kurawal juga penting untuk variabel biasa (${nama}, ingat episode tentang ekspansi), tapi di array ia mutlak diperlukan.Note
Kalian juga bisa mengisi array elemen-per-elemen: buah[0]="apel", buah[1]="mangga". Ini berguna saat nilai baru diketahui belakangan. Bash bahkan otomatis mengisi slot kosong: jika kalian menulis buah[5]="anggur" pada array kosong, elemen [0]–[4] akan menjadi kosong (diperlakukan seperti elemen tanpa nilai). Jarang diinginkan, tapi baik untuk diketahui.
"${arr[@]}" dan "${arr[*]}"Untuk mengakses seluruh isi array, ada dua notasi yang tampak mirip tapi berbeda artinya:
"${arr[@]}" — setiap elemen menjadi argumen/kata terpisah. Inilah yang hampir selalu kalian inginkan."${arr[*]}" — semua elemen digabung menjadi satu string yang dipisahkan karakter IFS (default spasi).daftar=("satu kata" "dua kata" "tiga kata")
for item in "${daftar[@]}"; do
echo "Item: $item"
done
echo "Gabungan: ${daftar[*]}"Perbedaan ini krusial saat elemen mengandung spasi. Dengan "${daftar[@]}", elemen "satu kata" tetap menjadi satu item; dengan "${daftar[*]}", semuanya menyatu menjadi satu string "satu kata dua kata tiga kata". Ini persis analog dengan perbedaan antara "$@" dan "$*" untuk argumen script yang mungkin sudah kalian temui.
Important
Selalu tulis "${arr[@]}" dengan tanda kutip saat mengiterasi atau meneruskan ke perintah — dan jangan pernah lupa kurung kurawal. "$arr[@]" (tanpa kurawal) sama sekali bukan array: Bash membaca $arr (elemen pertama) lalu literal [@]. Kesalahan ini menghasilkan output yang tidak pernah kalian harapkan. Rumus yang harus hafal di luar kepala: "${arr[@]}", tiga simbol — tanda kutip, kurung kurawal, dan @ — tidak boleh ada yang tertinggal.
Array tidak statis. Operasi yang paling sering dipakai:
daftar=("a" "b" "c")
echo "Jumlah: ${#daftar[@]}" # 3
daftar+=("d")
daftar+=("e" "f")
echo "Jumlah: ${#daftar[@]}" # 6
unset 'daftar[1]'
echo "Jumlah: ${#daftar[@]}" # 5
echo "Isi: ${daftar[@]}" # a c d e fMari bedah masing-masing:
${#daftar[@]} — tanda # di depan menghitung jumlah elemen. Ini bentuk "panjang" dari ${#str} yang menghitung panjang string.daftar+=("d") — sintaks append: menambahkan satu atau lebih elemen ke ujung array. Inilah cara yang benar, jauh lebih rapi daripada daftar[${#daftar[@]}]="d".unset 'daftar[1]' — menghapus elemen indeks 1. Perhatikan kutip: unset 'daftar[1]' melindungi tanda kurung dari ekspansi glob. Elemen yang dihapus menyisakan "lubang" — indeks lain tidak bergeser, jadi daftar[1] kini kosong dan jumlahnya berkurang.angka=(10 20 30 40 50)
sub=${angka[@]:1:2}
echo "Slice: $sub"
# 20 30
unset 'angka' # hapus seluruh array
echo "Jumlah: ${#angka[@]}" # 0Slice "${arr[@]:offset:length}" mengambil potongan mulai dari indeks offset sepanjang length — versi array dari pemotongan substring ${str:offset:length}.
for — Elemen Utuh, Bukan TerpecahIni yang menjadi kekuatan sejati array: mengiterasi seluruh elemen dengan for, dan karena kita memakai "${arr[@]}", setiap elemen yang mengandung spasi tetap utuh:
server=("web-01" "web-02" "db-01")
for host in "${server[@]}"; do
echo "Menghubungi $host..."
doneBandingkan dengan versi tanpa kutip dan kurawal — for host in $server — yang akan mencetak hanya web-01 (elemen pertama) karena $server tanpa indeks adalah elemen [0], dan for host in ${server[@]} yang akan memecah elemen berspasi. Hanya "${server[@]}" yang benar. Ini pola yang sudah kita tekankan sejak episode 11 dan berlaku di sini dengan kekuatan penuh.
Sering kali daftar yang dibutuhkan script berasal dari output sebuah perintah. Ada dua cara, dengan perbedaan yang sangat penting.
Cara yang keliru untuk ls misalnya — memakai command substitution langsung:
arr=($(ls *.txt))
echo "${#arr[@]}"Masalahnya sama seperti yang kita bahas di episode 11: hasil $(ls ...) dipecah berdasarkan spasi (word splitting), dan karakter glob ikut diekspansi. File catatan penting.txt menjadi dua elemen.
Cara yang benar adalah memakai mapfile (atau readarray) yang membaca output baris demi baris sebagai elemen:
mapfile -t files < <(ls *.txt)
echo "Jumlah file: ${#files[@]}"
for f in "${files[@]}"; do
echo "File: $f"
donemapfile -t membaca stdin baris per baris, memotong newline (-t), dan menyimpan tiap baris sebagai satu elemen. Proses pengisiannya sendiri sudah menjaga integritas baris, sehingga spasi di dalam nama file tidak menjadi masalah.
Sekarang kita rangkai semuanya. Skenario pertama: sebuah script memantau sejumlah server. Daftar server didefinisikan sekali sebagai array, lalu diiterasi:
#!/usr/bin/env bash
server=("192.168.1.10" "192.168.1.11" "192.168.1.12")
ok=0
gagal=0
for host in "${server[@]}"; do
if ping -c 1 -W 2 "$host" >/dev/null 2>&1; then
echo "OK : $host"
ok=$((ok + 1))
else
echo "FAIL : $host"
gagal=$((gagal + 1))
fi
done
echo "Ringkasan: $ok OK, $gagal gagal dari ${#server[@]} server."Perhatikan pola accumulator (ok dan gagal) yang bertambah di dalam loop, dan laporan akhir yang memakai ${#server[@]} untuk jumlah total. Ketika daftar server bertambah, script tidak berubah — cukup tambah satu elemen array.
Skenario kedua: backup beberapa file penting yang daftarnya tersimpan di array, dengan laporan per file:
#!/usr/bin/env bash
backup_dir="$HOME/backup-$(date +%F)"
mkdir -p "$backup_dir"
target=("/etc/hostname" "/etc/hosts" "/etc/fstab")
for file in "${target[@]}"; do
if [ -f "$file" ]; then
cp "$file" "$backup_dir/"
echo "Backup OK : $file"
else
echo "Tidak ada : $file"
fi
done
echo "Backup selesai di: $backup_dir"Script ini menunjukkan pembagian kerja yang rapi: data (array target) terpisah dari logika (loop dan kondisi). Inilah yang membuat script mudah dikembangkan — menambah file baru cukup mengubah satu baris array, tanpa menyentuh logika sama sekali.
Selanjutnya kita gabungkan materi episode 13 dengan array: bagaimana cara meneruskan sebuah array ke dalam fungsi. Penting untuk dipahami sejak awal: Bash tidak punya sintaks khusus untuk "meneruskan array sebagai argumen" — array adalah kumpulan nilai, bukan satu blok data. Idiom yang benar adalah menyebar elemen-elemennya dengan "${arr[@]}", lalu menerimanya di dalam fungsi lewat "$@":
#!/usr/bin/env bash
tampilkan_list() {
local label="$1"
shift
echo "$label:"
for item in "$@"; do
echo " - $item"
done
}
server=("web-01" "web-02" "db-01")
tampilkan_list "Server aktif" "${server[@]}"Ada dua detail yang layak kalian hafal:
"${server[@]}" di sisi pemanggil menyebar seluruh elemen menjadi argumen terpisah untuk fungsi — persis seperti ia menyebar elemen untuk for.shift di dalam fungsi membuang argumen pertama (label), sehingga "$@" setelahnya berisi sisa elemen array. Ini idiom umum saat sebuah fungsi menerima "opsi/keterangan" di depan dan "data" di belakang.Tanpa pola ini, kalian akan tergoda menulis tampilkan_list "Server aktif" "$server" — yang hanya meneruskan elemen pertama karena $server tanpa indeks. Dengan kombinasi "${arr[@]}" + "$@", seluruh array berpindah utuh ke dalam fungsi, dan fungsi bisa dipakai ulang untuk array mana pun.
Tip
Pola "${arr[@]}" + "$@" adalah jembatan antara dua episode yang paling produktif: array sebagai data, fungsi sebagai logika. Kalian bisa membangun pustaka fungsi pemrosesan array — daftar_server, daftar_file, print_list — yang menerima array apa pun tanpa perlu tahu isinya. Ini bentuk paling sederhana dari genericity yang sering dicari orang dari bahasa pemrograman, dan tersedia di Bash dengan sintaks sederhana ini.
| Kesalahan | Gejala | Solusi |
|---|---|---|
"${arr[@]}" tanpa tanda kutip | Elemen berspasi terpecah | Selalu "${arr[@]}" |
$arr tanpa indeks & kurawal | Hanya elemen pertama yang dipakai | Tulis ${arr[0]} atau "${arr[@]}" |
Memperlakukan array sebagai string (echo $arr) | Output hanya elemen pertama | Gunakan "${arr[@]}" atau "${arr[*]}" |
arr=($(cmd)) alih-alih mapfile | Output terpecah, glob diekspansi | mapfile -t arr < <(cmd) |
Lupa declare -a (jarang) | Variabel berperilaku sebagai string | Deklarasi eksplisit declare -a bila perlu |
unset arr[1] tanpa kutip | Glob/interpretasi tak terduga | unset 'arr[1]' |
Caution
Kesalahan paling berbahaya adalah memperlakukan array seperti string biasa: echo $arr hanya mencetak elemen pertama, dan "$arr" dalam perintah hanya meneruskan elemen pertama. Ketika script menerima hanya satu dari banyak elemen tanpa error apa pun, itu gejala klasiknya — tidak ada pesan kesalahan, hanya hasil yang salah. Saat array terasa "tidak lengkap", periksa dulu: apakah setiap penggunaan sudah memakai ${...} dan [@]/[*]?
Pada episode 14 ini kita telah menambahkan kekuatan penyimpanan kolektif ke script kalian. Dengan indexed array kita bisa menyimpan banyak nilai dalam satu variabel: mendeklarasikan (arr=("a" "b" "c")), mengakses per indeks (${arr[0]}), mengambil seluruh isi ("${arr[@]}"), menghitung jumlah (${#arr[@]}), menambah elemen (arr+=("d")), memotong (slice ${arr[@]:1:2}), dan menghapus (unset 'arr[1]'). Kita juga membangun array dari output perintah dengan mapfile dan merangkainya dalam praktik nyata memantau daftar server serta mem-backup daftar file.
Prinsip yang harus kalian bawa pulang: array adalah satu entitas berisi banyak nilai, dan selalu diakses lewat "${arr[@]}" — tiga simbol (kutip, kurawal, @) yang menjadi kebiasaan otomatis. Dengan data terstruktur dalam array dan logika yang dibungkus fungsi, script kalian kini bisa mengelola koleksi data dengan rapi.
Masih ada satu jenis array yang lebih canggih: associative array, yang tidak diindeks dengan angka melainkan dengan key berupa string. Di episode 15 selanjutnya kita akan membahasnya — pasangan key-value ala kamus, mapping service-ke-port, konfigurasi key-value, hingga frequency counter untuk menghitung kemunculan kata. Di sanalah data yang harus dicari berdasarkan nama, bukan nomor, akan terasa jauh lebih alami. Sampai jumpa di episode berikutnya!