Arrays & Associative Maps
Indexed Arrays
An indexed array maps integer subscripts to strings. Subscripts start at 0 and do not have to be contiguous.
Creating an Array
fruits=(apple banana cherry) # three elements, indices 0..2
fruits+=(date) # append one element
declare -a caps # explicit declaration
caps[0]=A; caps[2]=C # sparse: index 1 is unset
fruits=(apple banana cherry) is three elements. fruits=("apple banana cherry") is one element. Spaces separate; quotes bind.
Accessing Elements
echo "${fruits[0]}" # apple
echo "${fruits[-1]}" # date (last element, Bash 4.3+)
echo "${fruits[@]}" # all elements as separate words
echo "${fruits[*]}" # all elements joined into one word
echo "${#fruits[@]}" # number of elements
echo "${!fruits[@]}" # the indices themselves
Always quote "${arr[@]}". Unquoted ${arr[@]} re-splits each element on spaces, exactly like a bare $var.
Slicing
set -- one two three four
echo "${@:2:2}" # two three (2 elements from index 2)
a=(10 20 30 40 50)
echo "${a[@]:1:3}" # 20 30 40
Iterating
for f in "${fruits[@]}"; do
printf 'item: %s\n' "$f" # one iteration per element, spaces safe
done
for i in "${!fruits[@]}"; do
printf '%d -> %s\n' "$i" "${fruits[i]}"
done
Modifying and Removing
fruits[1]="blueberry" # replace
unset 'fruits[2]' # delete index 2 (quote it! otherwise glob risk)
fruits=() # empty the whole array
Associative Arrays
Declared with declare -A, associative arrays use arbitrary string keys. They are the closest thing Bash has to a dictionary.
Declaring and Filling
declare -A score
score[alice]=90
score[bob]=75
score+=( [carol]=88 [dave]=64 ) # add several at once
You must declare with
declare -A before the first assignment. Without it Bash creates an indexed array and score[alice] silently evaluates to index 0.
Reading and Iterating
echo "${score[alice]}" # 90
echo "${#score[@]}" # 4
for k in "${!score[@]}"; do
printf '%-6s %s\n' "$k" "${score[$k]}"
done
A Practical Lookup Table
declare -A ext=(
[sh]="shell" [py]="python"
[js]="javascript" [bash]="shell"
)
describe() {
local f="$1" e="${1##*.}"
printf '%s -> %s\n' "$f" "${ext[$e]:-unknown}"
}
describe notes.py # notes.py -> python
describe run.sh # run.sh -> shell
Pitfalls
- Unquoted
[@]: splits elements on spaces — always"${arr[@]}". Bash 3.2on macOS: no associative arrays and no negative indices. Install a newer Bash or avoid those features.- Passing arrays to functions: a function cannot see your array by name across a subshell; pass
"${arr[@]}"as arguments and rebuild withlocal -a copy=("$@"). - Sparse arrays:
${#a[@]}counts set elements, not the highest index + 1.