# Indexed and Associative Arrays — Bash / Shell Scripting

Source: https://www.skillbyai.com/en/bash/fn-arrays

> Store lists and key-value pairs in Bash arrays.

## Lists without word-splitting bugs

Arrays hold lists safely, including elements with spaces. **Indexed arrays**: `files=("a b.txt" c.txt)`, append with `files+=(d.txt)`, read with `"${files[0]}"`, all elements with **`"${files[@]}"`** (each element one word, the array equivalent of `"$@"`), count with `${#files[@]}` and indices with `${!files[@]}`. **Associative arrays** (Bash 4+, not available in macOS's built-in Bash 3.2) map keys to values: `declare -A ports=([web]=8080 [api]=9000)`, read `${ports[api]}`, iterate keys with `"${!ports[@]}"`. **`mapfile -t lines < file`** (also called `readarray`) reads a file into an array, one line per element. Arrays are the right way to build command lines dynamically: collect options in an array and run `"${cmd[@]}"`, instead of building a string and relying on word splitting. Bash arrays are one-dimensional; if you need nested data structures, it is time for another language or for `jq` with JSON.

## Arrays for safe command building

Each option stays a separate argument, even with spaces.

```bash
declare -A ports=([web]=8080 [api]=9000 [metrics]=9100)
for svc in "${!ports[@]}"; do
    printf '%-8s -> %s\n' "$svc" "${ports[$svc]}"
done

mapfile -t hosts < hosts.txt
echo "loaded ${#hosts[@]} hosts; first: ${hosts[0]}"

rsync_args=(-az --delete --exclude "*.tmp")
if [[ ${DRY_RUN:-0} == 1 ]]; then
    rsync_args+=(--dry-run)
fi
rsync "${rsync_args[@]}" "./site/" "deploy@web1:/var/www/my site/"
```

## A tray of labelled jars

A string with spaces is loose spices in one bag: you cannot tell where one ends and the next begins. An array is a tray of separate jars, each holding exactly one item, however oddly shaped.

**Quiz:** How do you expand every element of an array as separate, correctly quoted words?

- [ ] $arr
- [x] "${arr[@]}"
- [ ] ${arr}
- [ ] ${arr[*]}

*Answer:* "${arr[@]}". "${arr[@]}" expands each element as its own word, preserving spaces inside elements.
