Using Bash Associative Arrays for Fast Look‑ups in Scripts
Learn how Bash 4 associative arrays provide fast, in‑script key‑value look‑ups without external tools, plus version checks, scoping tips, and limits.
13 Jul 2025, 15:40 UTC

Problem: avoiding external tools for simple key‑value maps
Many Bash scripts need to translate identifiers (error codes, service names, configuration keys) into readable messages or values. A common approach writes these pairs to a temporary file and uses grep or awk to look them up, which adds process overhead and complicates error handling.
Thesis: Bash 4 associative arrays give O(1) look‑ups without leaving the shell
Starting with Bash 4, the built‑in declare -A command creates an associative array—a hash table where both keys and values are strings. Look‑ups, insertions, and deletions run in constant average time, and the data lives entirely in the script’s memory space.
Declaring and populating
To create an associative array named errmsg:
declare -A errmsg
Assign values using the key inside brackets:
errmsg[1]="Operation not permitted"
errmsg[2]="No such file or directory"
errmsg[13]="Permission denied"
Keys and values must be strings; numbers are automatically converted to their string representation.
Retrieving and iterating
Fetch a value with parameter expansion:
echo "Error 13: ${errmsg[13]}"
To walk through all entries, expand the keys with ${!arr[@]}:
for code in "${!errmsg[@]}"; do
echo "$code => ${errmsg[code]}"
done
Scope inside functions
When you need a private map inside a function, declare it with local -A:
lookup_error() {
local -A map
map[404]="Not Found"
map[500]="Internal Server Error"
echo "${map[$1]}"
}
The array disappears when the function returns, preventing name clashes.
Worked example: mapping HTTP status codes to messages
The following snippet defines a read‑only associative array and provides a helper function. No external programs are invoked.
#!/usr/bin/env bash
# Ensure Bash 4+
if (( BASH_VERSINFO[0] < 4 )); then
echo "This script requires Bash 4 or newer" >&2
exit 1
fi
declare -r -A http_status=(
[200]="OK"
[201]="Created"
[400]="Bad Request"
[401]="Unauthorized"
[403]="Forbidden"
[404]="Not Found"
[500]="Internal Server Error"
[502]="Bad Gateway"
[503]="Service Unavailable"
)
http_message() {
local code=$1
if [[ -z ${http_status[$code]+_} ]]; then
echo "Unknown status $code" >&2
return 1
fi
echo "${http_status[$code]}"
}
# Example usage
status=404
msg=$(http_message "$status")
if [[ $? -eq 0 ]]; then
echo "HTTP $status: $msg"
else
echo "Failed to retrieve message for $status" >&2
fi
To verify the script works, run it and confirm the output matches the expected message for the chosen status code. No external tools are needed for the lookup itself.
Trade‑offs and limitations
- String‑only keys and values: Bash associative arrays cannot store numbers or nested structures directly. Workarounds involve encoding complex data (e.g., JSON strings) or using indirect references, which adds complexity.
- Version requirement: The
declare -Asyntax is unavailable in Bash 3 and earlier, causing an "invalid option" error. Always checkBASH_VERSINFOor runbash --versionbefore relying on the feature. - Non‑POSIX compatibility: Scripts using associative arrays will not run under
dash,sh, or other Bourne‑like shells without modification. - Memory usage for very large maps: While efficient for hundreds to low‑thousands of entries, extremely large arrays may consume noticeable RAM and exhibit slower attribute access compared to purpose‑built libraries in languages like Python or Perl.
Actionable checklist
- Confirm Bash version:
bash --versionor test(( BASH_VERSINFO[0] >= 4 )). - Declare the array with
declare -A name(orlocal -Ainside functions). - Populate using
name[key]=value. - Retrieve with
${name[key]}and iterate viafor k in "${!name[@]}". - Handle missing keys gracefully (e.g., test with
[[ -z ${name[key]+_} ]]). - If portability to older Bash or POSIX shells is required, fall back to indexed arrays or external tools like
awk.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.