Chapter 07Lesson 02~75 minutes

Associative Arrays

Indexed arrays answer “what is item number 0?” Associative arrays answer “what value belongs to this key?” They are useful for small lookup tables, configuration maps, counters, and metadata when Bash remains the right abstraction level.

BeginnerArrays & dataHands-on lab

Learning objectives

By the end of this lesson

  • Declare associative arrays.
  • Assign and retrieve key-value pairs.
  • Check whether keys exist.
  • Iterate over keys and values.
  • Use maps without confusing missing and empty values.

1. Associative arrays require explicit declaration

declare -A ports

ports[api]=8080
ports[worker]=9090
ports[metrics]=9100

printf 'api port=%s\n' "${ports[api]}"

Unlike indexed arrays, associative keys are strings. Always use declare -A before assignment.

2. Compound assignment can initialize a map

declare -A images=(
  [api]="registry.example/api:2.0"
  [worker]="registry.example/worker:2.0"
  [cache]="redis:7"
)

printf '%s\n' "${images[worker]}"

3. ${!map[@]} expands the keys

for service in "${!images[@]}"; do
  printf 'service=%s image=%s\n' \
    "$service" "${images[$service]}"
done
Ordering

Do not treat associative-array iteration order as a stable business interface. If order matters, sort the keys or maintain a separate ordered array.

4. Check key existence separately from value emptiness

declare -A config
config[region]=""
config[environment]="staging"

if [[ -v 'config[region]' ]]; then
  printf 'region key exists, value=<%s>\n' "${config[region]}"
fi

if [[ ! -v 'config[missing]' ]]; then
  printf 'missing key does not exist\n'
fi

An existing key can intentionally hold an empty string. That differs from an absent key.

5. Parameter expansion can supply missing-value defaults

declare -A config=(
  [environment]="staging"
)

region=${config[region]:-eu-central-1}
printf 'region=%s\n' "$region"

Remember that the :- form treats both missing and empty values as needing the default. Use the no-colon form when empty must remain meaningful.

6. unset removes a key

declare -A state=(
  [api]="ready"
  [worker]="ready"
  [cache]="degraded"
)

unset 'state[cache]'

printf 'keys: %s\n' "${!state[@]}"

7. Associative arrays can implement small counters

declare -A failures=()

for service in api api worker api; do
  (( failures["$service"] += 1 ))
done

for service in "${!failures[@]}"; do
  printf '%s failures=%d\n' "$service" "${failures[$service]}"
done

This is useful for lightweight aggregation, but large datasets or complex grouping usually belong in awk, Python, or another data-processing tool.

8. Maps are useful for translating symbolic names

declare -A contexts=(
  [dev]="cluster-dev"
  [staging]="cluster-stg"
  [prod]="cluster-prod"
)

environment=${1:-staging}

if [[ ! -v 'contexts[$environment]' ]]; then
  printf 'unsupported environment: %s\n' "$environment" >&2
  exit 65
fi

context=${contexts[$environment]}
printf 'context=%s\n' "$context"

9. Associative arrays are not nested object graphs

A Bash associative array maps one string key to one string value. It does not natively store nested dictionaries, typed objects, or JSON-like trees.

declare -A service_meta
service_meta[api.image]="api:2.0"
service_meta[api.port]="8080"
Complexity signal

Flattened keys such as api.image can work for tiny maps, but deep structured state is a strong sign that JSON plus jq, Python, or another language is a better fit.

10. Do not invent an ad-hoc map serialization casually

Joining keys and values with commas, colons, or spaces becomes ambiguous as soon as data can contain those characters. If the map must cross a process or storage boundary, use a real format such as JSON, env-style key-value data with a strict contract, or a purpose-built file format.

11. Hands-on lab: environment-to-cluster lookup

mkdir -p "$HOME/devops-academy/bash/chapter07/lesson02"
cd "$HOME/devops-academy/bash/chapter07/lesson02"

cat > lookup.sh <<'EOF'
#!/usr/bin/env bash

declare -A cluster=(
  [dev]="dev-cluster"
  [staging]="staging-cluster"
  [prod]="prod-cluster"
)

declare -A namespace=(
  [dev]="sandbox"
  [staging]="preprod"
  [prod]="production"
)

environment=${1:-}

if [[ ! -v 'cluster[$environment]' ]]; then
  printf 'unknown environment: %s\n' "$environment" >&2
  exit 65
fi

printf 'environment=%s\n' "$environment"
printf 'cluster=%s\n' "${cluster[$environment]}"
printf 'namespace=%s\n' "${namespace[$environment]}"
EOF

bash lookup.sh staging
bash lookup.sh prod
bash lookup.sh qa || true

Verification checklist

12. Knowledge check

Question 1. How do you declare an associative array?

Question 2. How do you expand all keys?

Question 3. Why is checking key existence different from checking for a non-empty value?

Question 4. Are associative arrays a good representation for deeply nested JSON-like data?

13. Summary

Associative arrays provide small key-value maps inside Bash. They are excellent for configuration lookups, labels, counters, and simple metadata, provided you keep ordering and structural limitations in mind.

14. Further reading

  • GNU Bash Reference Manual — Arrays.
  • GNU Bash Reference Manual — Bash Conditional Expressions: -v.
  • GNU Bash Reference Manual — Arithmetic Evaluation.
  • ShellCheck documentation — associative-array usage.
Next lesson

Safe Array Expansion and Quoting

Continue Chapter 7 by building a safer model for structured shell state.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.