Skip to content
C.W.K.
Stream
Lesson 08 of 12 · published

Arrays

~10 min · arrays, indexed, associative

Level 0Window Tourist
0 XP0/95 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

Indexed arrays (bash and zsh)

files=("a.txt" "b.txt" "c.txt")
echo "${files[0]}"        # a.txt (bash) or empty (zsh — see below)
echo "${files[@]}"        # all elements
echo "${#files[@]}"       # count: 3
files+=("d.txt")          # append
unset 'files[1]'           # remove the b.txt slot

bash arrays start at 0, zsh at 1 by default. Add setopt KSH_ARRAYS in zsh to get bash semantics. The difference catches everyone the first time.

Iterating

for f in "${files[@]}"; do
  echo "$f"
done

# With index
for i in "${!files[@]}"; do
  echo "$i: ${files[i]}"
done

Associative arrays (bash 4+, zsh)

declare -A user
user[name]="Alice"
user[age]=24
for k in "${!user[@]}"; do
  echo "$k = ${user[$k]}"
done

macOS bash 3.2 doesn't have associative arrays. Either install bash 5 via brew, or use zsh, or fall back to parallel indexed arrays.

Reading a command into an array

readarray -t lines < ~/.zshrc        # bash 4+
lines=("${(@f)$(< ~/.zshrc)}")             # zsh
files=(*.txt)                              # glob

Slicing

echo "${files[@]:1:2}"   # 2 elements starting at index 1
echo "${files[@]: -1}"   # last element (note the space)

An array is not a space-joined string

Arrays preserve each filename or user value as a separate item. Concatenating items="$a $b" loses whether spaces belonged to data. Store values separately and pass "${items[@]}".

Crossing a shell boundary requires serialization

You cannot export a Bash array intact as an environment variable. Pass multiple arguments or serialize with an explicit line, NUL, or JSON contract. Similar array syntax does not imply the same data protocol.

Code

Real array workflow·bash
#!/usr/bin/env bash
set -euo pipefail
todos=()
while IFS= read -r line; do
  [[ "$line" =~ ^TODO ]] && todos+=("$line")
done < notes.md
echo "${#todos[@]} TODO lines"
printf '  - %s\n' "${todos[@]}"

External links

Exercise

In a bash script: arr=(a b c d); print all four ways: "${arr[@]}", "${arr[*]}", "${arr[1]}", "${#arr[@]}". Note where the boundaries differ.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.