Associative Arrays
Associative arrays (also called dictionaries or hash maps) use strings as keys instead of numeric indices. They're perfect for key-value data.
Creating Associative Arrays
Must be declared explicitly with declare -A:
#!/bin/bash
# Declare and initialize
declare -A USER
USER[name]="Alice"
USER[age]=30
USER[city]="Boston"
# Or all at once
declare -A CONFIG=(
[host]="localhost"
[port]="8080"
[debug]="true"
)
Accessing Values
#!/bin/bash
declare -A USER=(
[name]="Alice"
[email]="alice@example.com"
)
# Access single value
echo "${USER[name]}" # Alice
echo "${USER[email]}" # alice@example.com
# Check if key exists
if [[ -v USER[name] ]]; then
echo "Name key exists"
fi
Getting All Keys and Values
#!/bin/bash
declare -A COLORS=(
[sky]="blue"
[grass]="green"
[sun]="yellow"
)
# All keys
echo "${!COLORS[@]}" # sky grass sun (order not guaranteed)
# All values
echo "${COLORS[@]}" # blue green yellow
# Number of elements
echo "${#COLORS[@]}" # 3
Exercise: Create Associative Array
Work with key-value pairs:
Looping Over Associative Arrays
#!/bin/bash
declare -A SCORES=(
[alice]=95
[bob]=87
[carol]=92
)
# Loop over keys
for name in "${!SCORES[@]}"; do
echo "$name: ${SCORES[$name]}"
done
# Loop with formatted output
for key in "${!SCORES[@]}"; do
printf "%-10s %d\n" "$key" "${SCORES[$key]}"
done
Modifying Associative Arrays
#!/bin/bash
declare -A CONFIG=([debug]="false")
# Add/update
CONFIG[host]="localhost"
CONFIG[debug]="true"
# Remove key
unset 'CONFIG[debug]'
# Clear entire array
unset CONFIG
declare -A CONFIG # Recreate empty
Checking for Keys
#!/bin/bash
declare -A DATA=([foo]="bar")
# Method 1: -v test (Bash 4.3+)
if [[ -v DATA[foo] ]]; then
echo "foo exists"
fi
# Method 2: Check for empty (but fails if value is empty string)
if [[ -n "${DATA[foo]+x}" ]]; then
echo "foo exists"
fi
# Method 3: Loop through keys
for key in "${!DATA[@]}"; do
[[ "$key" == "foo" ]] && echo "Found foo"
done
Exercise: Loop Over Keys
Iterate through an associative array:
Parsing Key-Value Data
#!/bin/bash
# Parse config file format: key=value
declare -A CONFIG
while IFS='=' read -r key value; do
# Skip empty lines and comments
[[ -z "$key" || "$key" =~ ^# ]] && continue
CONFIG["$key"]="$value"
done << 'EOF'
host=localhost
port=8080
debug=true
EOF
echo "Host: ${CONFIG[host]}"
echo "Port: ${CONFIG[port]}"
Nested Data Simulation
Bash doesn't support nested arrays, but you can simulate:
#!/bin/bash
# Store structured data with compound keys
declare -A USERS
USERS[alice:name]="Alice Smith"
USERS[alice:email]="alice@example.com"
USERS[alice:role]="admin"
USERS[bob:name]="Bob Jones"
USERS[bob:email]="bob@example.com"
USERS[bob:role]="user"
# Access
echo "${USERS[alice:name]}" # Alice Smith
# List all for a user
for key in "${!USERS[@]}"; do
if [[ "$key" == alice:* ]]; then
echo "$key = ${USERS[$key]}"
fi
done
Counting Occurrences
#!/bin/bash
WORDS=("apple" "banana" "apple" "cherry" "banana" "apple")
declare -A COUNTS
for word in "${WORDS[@]}"; do
((COUNTS[$word]++))
done
for word in "${!COUNTS[@]}"; do
echo "$word: ${COUNTS[$word]}"
done
# apple: 3
# banana: 2
# cherry: 1
Grouping Data
#!/bin/bash
# Group files by extension
declare -A BY_EXT
for file in *; do
ext="${file##*.}"
BY_EXT[$ext]+="$file "
done
for ext in "${!BY_EXT[@]}"; do
echo "$ext files: ${BY_EXT[$ext]}"
done
Practical Example: Environment Config
#!/bin/bash
declare -A DEV_CONFIG=(
[db_host]="localhost"
[db_port]="5432"
[debug]="true"
)
declare -A PROD_CONFIG=(
[db_host]="prod.db.example.com"
[db_port]="5432"
[debug]="false"
)
# Select config based on environment
ENV="${1:-dev}"
declare -n CONFIG="${ENV^^}_CONFIG"
echo "Database: ${CONFIG[db_host]}:${CONFIG[db_port]}"
echo "Debug: ${CONFIG[debug]}"
Key Takeaways
- Must use
declare -Ato create associative arrays - Access with
${ARRAY[key]}where key is a string - Get all keys with
${!ARRAY[@]} - Check key exists with
[[ -v ARRAY[key] ]] - Loop:
for key in "${!ARRAY[@]}"; do ... done - Remove key with
unset 'ARRAY[key]' - Order is not guaranteed (hash-based)
- Simulate nesting with compound keys:
ARRAY[user:name] - Great for counting, grouping, and config data

