Arrays
Bash arrays: indexed, associative, slicing, expansion, iteration. The patterns that keep scripts readable.
Linux — Bash arrays
EXAMPLE
# ===== Indexed arrays =====
arr=(apple banana cherry)
arr[0] # 'apple' (use ${arr[0]})
${arr[1]} # 'banana'
# All elements:
${arr[@]} # apple banana cherry
${arr[*]} # same, but as ONE string when quoted
# Length:
${#arr[@]} # 3
# Append:
arr+=('date')
# Last:
${arr[-1]} # 'date' (Bash 4.3+)
# ===== Iteration =====
for fruit in "${arr[@]}"; do
echo "$fruit"
done
# With index:
for i in "${!arr[@]}"; do
echo "$i: ${arr[i]}"
done
# ===== Slicing =====
${arr[@]:1:2} # 2 elements starting at index 1 -> banana cherry
${arr[@]:2} # from index 2 to end
# ===== From command output =====
mapfile -t files < <(ls *.txt)
# or
readarray -t files < <(ls *.txt)
for f in "${files[@]}"; do
echo "$f"
done
# ===== From string =====
str='a,b,c,d'
IFS=',' read -ra parts <<< "$str"
echo "${parts[1]}" # 'b'
# ===== Remove element =====
unset 'arr[1]' # removes index 1; LEAVES a 'hole'
arr=("${arr[@]}") # re-index to fill the hole
# ===== Associative arrays (hash maps) =====
declare -A ages
ages['alex']=30
ages['sam']=25
echo "${ages['alex']}" # 30
echo "${!ages[@]}" # keys: alex sam
echo "${ages[@]}" # values: 30 25
echo "${#ages[@]}" # 2
# Iterate:
for name in "${!ages[@]}"; do
echo "$name is ${ages[$name]}"
done
# Check existence:
if [[ -v ages['alex'] ]]; then
echo 'exists'
fi
# Delete:
unset 'ages[alex]'
# ===== Common patterns =====
# Build a SET of unique items:
declare -A seen
for x in "$@"; do
seen["$x"]=1
done
echo "unique: ${!seen[@]}"
# Count occurrences:
declare -A counts
for word in $(cat words.txt); do
counts["$word"]=$(( ${counts[$word]:-0} + 1 ))
done
# ===== Function returning array via global =====
get_files() {
files=("$@") # use a known global
}
get_files *.txt
echo "${files[@]}"
# Or via nameref (Bash 4.3+):
get_files2() {
local -n out=$1
out=("${@:2}")
}
get_files2 result a b c
echo "${result[@]}" # a b c
# ===== Patterns =====
# - Always quote "${arr[@]}" — without quotes, words split
# - mapfile / readarray for command output
# - declare -A for hash maps
# - Use ${#arr[@]} for length, NOT $#
# ===== Pitfalls =====
# - ${arr[@]} unquoted -> spaces in elements break
# - Holes from unset; re-index if needed
# - Sparse arrays look full but skip indexes
# - Word-splitting in for x in $str (use IFS + read -ra)
Why it matters
Bash arrays: indexed for ordered, associative for hash maps, mapfile for command output, IFS + read -ra for parsing strings. Always quote "\${arr[@]}" to avoid word splitting. Once these patterns are reflex, scripts past 50 lines stay readable.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
fruits=(apple banana cherry)
echo "${fruits[1]}"
for f in "${fruits[@]}"; do echo "$f"; done
Try it Yourself »
Discussion
Loading…