Belajar BASH Scripting - Memahami Indexed Array
Episode 14 of 27

Belajar BASH Scripting - Memahami Indexed Array

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.

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

Pendahuluan

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.

Pembahasan Utama

Mengapa Array?

Sebelum sintaks, mari kita tegaskan masalah yang dipecahkan array. Perhatikan pendekatan tanpa array untuk mengelola beberapa server:

Tanpa array: variabel yang menumpuk
server1="web-01"
server2="web-02"
server3="db-01"
 
echo "$server1"
echo "$server2"
echo "$server3"
Semakin banyak server, semakin banyak variabel

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.

Deklarasi dan Akses Dasar

Array di Bash dideklarasikan dengan tanda kurung dan elemen dipisahkan spasi:

Deklarasi array dan akses elemen
buah=("apel" "mangga" "pisang")
 
echo "${buah[0]}"
echo "${buah[1]}"
echo "${buah[2]}"
# apel
# mangga
# pisang
Indeks dimulai dari 0, diakses dengan kurung siku

Ada dua hal yang wajib kalian perhatikan dalam sintaks akses:

  1. Indeks dimulai dari 0. Elemen pertama adalah arr[0], bukan arr[1]. Ini konvensi universal yang sama dengan bahasa C dan hampir semua bahasa modern.
  2. Kurung kurawal {} 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.

Semua Elemen: "${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).
@ vs * di dalam tanda kutip
daftar=("satu kata" "dua kata" "tiga kata")
 
for item in "${daftar[@]}"; do
    echo "Item: $item"
done
 
echo "Gabungan: ${daftar[*]}"
Di dalam kutip, @ menjaga setiap elemen tetap utuh

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.

Menghitung, Menambah, dan Menghapus Elemen

Array tidak statis. Operasi yang paling sering dipakai:

Operasi dasar array
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 f
Jumlah, append, dan hapus elemen

Mari 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.
Memotong (slice) dan menghapus seluruh
angka=(10 20 30 40 50)
sub=${angka[@]:1:2}
echo "Slice: $sub"
# 20 30
 
unset 'angka'      # hapus seluruh array
echo "Jumlah: ${#angka[@]}"    # 0
Slice dimulai dari indeks 1 sepanjang 2 elemen

Slice "${arr[@]:offset:length}" mengambil potongan mulai dari indeks offset sepanjang length — versi array dari pemotongan substring ${str:offset:length}.

Iterasi dengan for — Elemen Utuh, Bukan Terpecah

Ini yang menjadi kekuatan sejati array: mengiterasi seluruh elemen dengan for, dan karena kita memakai "${arr[@]}", setiap elemen yang mengandung spasi tetap utuh:

Iterasi array dengan elemen berspasi
server=("web-01" "web-02" "db-01")
 
for host in "${server[@]}"; do
    echo "Menghubungi $host..."
done
Setiap elemen jadi satu iterasi, spasi di dalam elemen aman

Bandingkan 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.

Membangun Array dari Output Perintah

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:

Pola yang keliru: word splitting
arr=($(ls *.txt))
echo "${#arr[@]}"
Output ber-spasi atau glob karakter akan terpecah

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:

Pola yang benar: mapfile
mapfile -t files < <(ls *.txt)
echo "Jumlah file: ${#files[@]}"
for f in "${files[@]}"; do
    echo "File: $f"
done
mapfile menyimpan satu baris per elemen

mapfile -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.

Praktik 1: Memantau Daftar Server

Sekarang kita rangkai semuanya. Skenario pertama: sebuah script memantau sejumlah server. Daftar server didefinisikan sekali sebagai array, lalu diiterasi:

Ping massal dengan array server
#!/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."
Satu array, satu loop, satu laporan

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.

Praktik 2: Daftar File untuk Backup

Skenario kedua: backup beberapa file penting yang daftarnya tersimpan di array, dengan laporan per file:

Backup file-file penting
#!/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"
Array daftar file diproses satu per satu

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.

Meneruskan Array ke Fungsi

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 "$@":

Meneruskan array ke fungsi
#!/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[@]}"
Array disebar jadi argumen fungsi, diterima via

Ada dua detail yang layak kalian hafal:

  1. "${server[@]}" di sisi pemanggil menyebar seluruh elemen menjadi argumen terpisah untuk fungsi — persis seperti ia menyebar elemen untuk for.
  2. 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 Umum dalam Array

KesalahanGejalaSolusi
"${arr[@]}" tanpa tanda kutipElemen berspasi terpecahSelalu "${arr[@]}"
$arr tanpa indeks & kurawalHanya elemen pertama yang dipakaiTulis ${arr[0]} atau "${arr[@]}"
Memperlakukan array sebagai string (echo $arr)Output hanya elemen pertamaGunakan "${arr[@]}" atau "${arr[*]}"
arr=($(cmd)) alih-alih mapfileOutput terpecah, glob diekspansimapfile -t arr < <(cmd)
Lupa declare -a (jarang)Variabel berperilaku sebagai stringDeklarasi eksplisit declare -a bila perlu
unset arr[1] tanpa kutipGlob/interpretasi tak terdugaunset '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 [@]/[*]?

Penutup

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!

Belajar BASH Scripting - Memahami Indexed Array | Belajar BASH Scripting