iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

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…