Associative_arrays
Chapter 12: Associative Arrays
Section titled “Chapter 12: Associative Arrays”Overview
Section titled “Overview”Associative arrays in bash (available in Bash 4+) allow you to store data using key-value pairs. This is similar to dictionaries or hashes in other programming languages. This chapter covers declaring, accessing, and using associative arrays for DevOps configurations, caching, and data management.
Associative Array Basics
Section titled “Associative Array Basics”Declaration
Section titled “Declaration”#!/usr/bin/env bash# Must declare before use (Bash 4+)declare -A config
# Assign valuesconfig[host]="localhost"config[port]="8080"config[database]="myapp"config[debug]="true"
# Or initialize all at oncedeclare -A settings=( [host]="localhost" [port]="8080" [database]="myapp" [debug]="true")Accessing Values
Section titled “Accessing Values”Basic Access
Section titled “Basic Access”#!/usr/bin/env bashdeclare -A useruser[name]="John Doe"user[email]="john@example.com"user[role]="admin"
# Access by keyecho "Name: ${user[name]}"echo "Email: ${user[email]}"echo "Role: ${user[role]}"
# Alternative syntaxecho "Name: ${user[name]}"echo "Email: ${user[email]}"All Keys and Values
Section titled “All Keys and Values”#!/usr/bin/env bashdeclare -A serverserver[web01]="192.168.1.10"server[web02]="192.168.1.11"server[db01]="192.168.1.20"
# All keysecho "Keys: ${!server[@]}"
# All valuesecho "Values: ${server[@]}"
# Number of elementsecho "Count: ${#server[@]}"Iterating Over Associative Arrays
Section titled “Iterating Over Associative Arrays”Iterate Keys and Values
Section titled “Iterate Keys and Values”#!/usr/bin/env bashdeclare -A colorscolors[red]="#FF0000"colors[green]="#00FF00"colors[blue]="#0000FF"
# Iterate over keysecho "Servers:"for key in "${!colors[@]}"; do echo " $key = ${colors[$key]}"done
# Iterate over valuesecho "Colors:"for value in "${colors[@]}"; do echo " $value"donePractical Examples
Section titled “Practical Examples”Example 1: Server Configuration
Section titled “Example 1: Server Configuration”#!/usr/bin/env bashdeclare -A servers
# Web serversservers[web01]="192.168.1.10"servers[web02]="192.168.1.11"servers[web03]="192.168.1.12"
# Database serversservers[db01]="192.168.2.10"servers[db02]="192.168.2.11"
# Cache serversservers[cache01]="192.168.3.10"
echo "Server inventory:"echo "=================="
# Group by typefor key in "${!servers[@]}"; do ip="${servers[$key]}" type="${key%%[0-9]*}" printf "%-10s %-15s %s\n" "$type" "$key" "$ip"doneExample 2: Environment Variables
Section titled “Example 2: Environment Variables”#!/usr/bin/env bash# Configuration for different environmentsdeclare -A prod_configprod_config[db_host]="prod-db.example.com"prod_config[db_port]="5432"prod_config[max_connections]="200"prod_config[log_level]="warn"
declare -A staging_configstaging_config[db_host]="staging-db.example.com"staging_config[db_port]="5432"staging_config[max_connections]="50"staging_config[log_level]="debug"
declare -A dev_configdev_config[db_host]="localhost"dev_config[db_port]="5432"dev_config[max_connections]="10"dev_config[log_level]="debug"
# Function to load configload_config() { local env="$1" local -n config="$env_config"
case "$env" in production) config=prod_config ;; staging) config=staging_config ;; development) config=dev_config ;; esac
echo "Loaded $env configuration:" for key in "${!config[@]}"; do echo " $key = ${config[$key]}" done}
# Usageload_config "production"Example 3: Cache Implementation
Section titled “Example 3: Cache Implementation”#!/usr/bin/env bashdeclare -A cachedeclare -A cache_expiry
# Add to cachecache_set() { local key="$1" local value="$2" local ttl="${3:-300}" # Default 5 minutes
cache["$key"]="$value" cache_expiry["$key"]=$(($(date +%s) + ttl))}
# Get from cachecache_get() { local key="$1" local now=$(date +%s)
# Check if key exists if [ -z "${cache[$key]+exists}" ]; then return 1 # Not found fi
# Check if expired if [ $now -gt ${cache_expiry[$key]:-0} ]; then unset cache["$key"] unset cache_expiry["$key"] return 1 # Expired fi
echo "${cache[$key]}" return 0}
# Clear cachecache_clear() { local key="$1" unset cache["$key"] unset cache_expiry["$key"]}
# Usagecache_set "user_123" "John Doe" 60cache_get "user_123" && echo "Found" || echo "Not found"
sleep 2cache_get "user_123" && echo "Found" || echo "Expired or not found"Example 4: Metrics Collection
Section titled “Example 4: Metrics Collection”#!/usr/bin/env bashdeclare -A metrics
# Record metricrecord_metric() { local name="$1" local value="$2" metrics["$name"]="$value"}
# Get metricget_metric() { local name="$1" echo "${metrics[$name]:-0}"}
# Increment counterincrement_counter() { local name="$1" local current=${metrics[$name]:-0} metrics["$name"]=$((current + 1))}
# Record CPU usagerecord_metric "cpu_usage" "45"record_metric "memory_usage" "72"record_metric "disk_usage" "68"
# Increment request counterincrement_counter "requests_total"increment_counter "requests_total"increment_counter "requests_total"
echo "Metrics:"for key in "${!metrics[@]}"; do echo " $key = ${metrics[$key]}"doneExample 5: Command-Line Flags
Section titled “Example 5: Command-Line Flags”#!/usr/bin/env bashdeclare -A flags
# Parse flagsparse_flags() { while [ $# -gt 0 ]; do case "$1" in -v|--verbose) flags[verbose]=true shift ;; -f|--force) flags[force]=true shift ;; -q|--quiet) flags[quiet]=true shift ;; -o|--output) flags[output]="$2" shift 2 ;; *) echo "Unknown flag: $1" return 1 ;; esac done}
# Check flaghas_flag() { local flag="$1" [ "${flags[$flag]:-false}" = "true" ]}
# Parse example flagsparse_flags -v -f --output /tmp/out.txt
# Check flagsif has_flag verbose; then echo "Verbose mode enabled"fi
if has_flag force; then echo "Force mode enabled"fi
echo "Output: ${flags[output]:-stdout}"Example 6: File Type Detection
Section titled “Example 6: File Type Detection”#!/usr/bin/env bashdeclare -A mime_types
# Initialize common typesmime_types[txt]="text/plain"mime_types[html]="text/html"mime_types[css]="text/css"mime_types[js]="application/javascript"mime_types[json]="application/json"mime_types[pdf]="application/pdf"mime_types[zip]="application/zip"mime_types[png]="image/png"mime_types[jpg]="image/jpeg"mime_types[jpeg]="image/jpeg"mime_types[gif]="image/gif"mime_types[svg]="image/svg+xml"mime_types[xml]="application/xml"
# Get MIME typeget_mime_type() { local file="$1" local ext="${file##*.}"
if [ -n "${mime_types[$ext]:-}" ]; then echo "${mime_types[$ext]}" else echo "application/octet-stream" fi}
# Usagefor file in document.txt image.png script.js data.json; do echo "$file -> $(get_mime_type "$file")"doneAdvanced Operations
Section titled “Advanced Operations”Check if Key Exists
Section titled “Check if Key Exists”#!/usr/bin/env bashdeclare -A configconfig[host]="localhost"config[port]="8080"
# Check key existsif [ -n "${config[host]+exists}" ]; then echo "Key 'host' exists: ${config[host]}"fi
# Check key doesn't existif [ -z "${config[debug]+exists}" ]; then echo "Key 'debug' does not exist"fiDelete Key-Value Pair
Section titled “Delete Key-Value Pair”#!/usr/bin/env bashdeclare -A datadata[key1]="value1"data[key2]="value2"
echo "Before: ${!data[@]}"unset data[key1]echo "After: ${!data[@]}"Copy Associative Array
Section titled “Copy Associative Array”#!/usr/bin/env bashdeclare -A sourcesource[a]="1"source[b]="2"
# Copy to destinationdeclare -A destfor key in "${!source[@]}"; do dest["$key"]="${source[$key]}"done
echo "Copied: ${dest[@]}"Best Practices
Section titled “Best Practices”Use Meaningful Keys
Section titled “Use Meaningful Keys”# Good: Descriptive keysdeclare -A server_configserver_config[hostname]="web01"server_config[ip_address]="192.168.1.10"
# Avoid: Cryptic keysdeclare -A bad_configbad_config[h]="web01"bad_config[ip]="192.168.1.10"Always Declare Before Use
Section titled “Always Declare Before Use”# WRONG: May not work on all bash versionsconfig[key]="value"
# CORRECT: Always declaredeclare -A configconfig[key]="value"Summary
Section titled “Summary”In this chapter, you learned about:
- ✅ Associative array declaration
- ✅ Accessing values
- ✅ Iterating over keys and values
- ✅ Practical examples
- ✅ Advanced operations
- ✅ Best practices
Exercises
Section titled “Exercises”Level 1: Basics
Section titled “Level 1: Basics”- Create an associative array for user data
- Access and print all key-value pairs
- Check if a key exists
Level 2: Intermediate
Section titled “Level 2: Intermediate”- Implement a configuration system
- Create a cache mechanism
- Build a metrics collector
Level 3: Advanced
Section titled “Level 3: Advanced”- Implement a flag parser
- Create a file type mapping system
- Build a multi-environment configuration manager
Next Steps
Section titled “Next Steps”Continue to the next chapter to learn about string manipulation.
Previous Chapter: Arrays Next Chapter: String Manipulation