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]="Pippa"
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)

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.