Bash associative array examples
October 17, 2012 [bash, Programming Languages, Tech]Quick reference of things I discovered about how to use associative arrays in bash. Note: bash version 4 only.
(See also Bash Arrays.)
Basics
$ declare -A MYMAP # Create an associative array
$ MYMAP[foo]=bar # Put a value into an associative array
$ echo ${MYMAP[foo]} # Get a value out of an associative array
bar
$ echo MYMAP[foo] # WRONG
MYMAP[foo]
$ echo $MYMAP[foo] # WRONG
[foo]
Creating
$ declare -A MYMAP # Explicitly declare $ MYMAP[foo]=bar # Or this line implicitly makes it an associative array (in global scope, bash 4.2+ only) $ MYMAP[baz]=quux # Can add multiple values one by one $ MYMAP[corge]=grault
$ declare -A MYMAP=( [foo]=bar [baz]=quux [corge]=grault ) # Initialise all at once$ echo ${MYMAP[foo]} bar $ echo ${MYMAP[baz]} quux
$ declare -A MYMAP # Or declare separately
$ MYMAP=( [foo]=bar [baz]=quux [corge]=grault ) # Then initialise
$ echo ${MYMAP[foo]}
bar
$ echo ${MYMAP[baz]}
quux
Variables as keys
$ K=baz
$ MYMAP[$K]=quux # Use a variable as key to put a value into an associative array
$ echo ${MYMAP[$K]} # Use a variable as key to extract a value from an associative array
quux
$ echo ${MYMAP[baz]} # Obviously the value is accessible via the literal key
quux
Quoting keys
$ declare -A MYMAP
$ MYMAP[foo A]="bar B" # Quoting keys makes no difference
$ MYMAP["corge X"]="grault Y" # Quoting keys makes no difference
$ echo ${MYMAP["corge X"]} # You can access by quoting
grault Y
$ echo ${MYMAP[corge X]} # Or not bother
grault Y
$ echo ${MYMAP[foo A]}
bar B
$ MYMAP['waldo 1']="fred 2" # Single quotes also make no difference
$ echo ${MYMAP['waldo 1']}
fred 2
$ echo ${MYMAP[waldo 1]}
fred 2
$ K=plugh
$ MYMAP['$K']=xyzzy # Except single quotes prevent variable expansion, as usual
$ echo ${MYMAP[plugh]}
$ echo ${MYMAP['$K']}
xyzzy
Missing keys
$ MYMAP[foo]=bar
$ echo ${MYMAP[missing]} # Accessing a missing value gives ""
$ # Testing whether a value is missing from an associative array
$ if [ ${MYMAP[foo]+_} ]; then echo "Found"; else echo "Not found"; fi
Found
$ if [ ${MYMAP[missing]+_} ]; then echo "Found"; else echo "Not found"; fi
Not found
Looping
$ declare -A MYMAP=( [foo a]=bar [baz b]=quux )
$ echo "${!MYMAP[@]}" # Print all keys - quoted, but quotes removed by echo
foo a baz b
$ # Loop through all keys in an associative array
$ for K in "${!MYMAP[@]}"; do echo $K; done
foo a
baz b
$ for K in ${!MYMAP[@]}; do echo $K; done # WRONG
foo
a
baz
b
$ # Looping through keys and values in an associative array
$ for K in "${!MYMAP[@]}"; do echo $K --- ${MYMAP[$K]}; done
foo a --- bar
baz b --- quux
$ # Loop through all values in an associative array
$ for V in "${MYMAP[@]}"; do echo $V; done
bar
quux
Clearing
$ declare -A MYMAP
$ MYMAP[foo]=bar
$ echo ${MYMAP[foo]}
bar
$ declare -A MYMAP # Re-declaring DOES NOT clear an associative array
$ echo ${MYMAP[foo]}
bar
$ unset MYMAP # You need to unset and re-declare to get a cleared associative array
$ declare -A MYMAP
$ echo ${MYMAP[foo]}
Deleting keys
$ MYMAP[foo]=bar
$ echo ${MYMAP[foo]}
bar
$ unset ${MYMAP[foo]} # WRONG
$ echo ${MYMAP[foo]}
bar
$ unset MYMAP[foo] # To delete from an associative array, use "unset" with similar syntax to assigning
$ # BUT see next section if key contains spaces
$ echo ${MYMAP[foo]}
$ MYMAP[baz]=quux
$ echo ${MYMAP[baz]}
quux
$ K=baz
$ unset MYMAP[$K] # Can unset using a variable for the key too
$ # BUT see next section if variable may contain spaces - always better to quote
$ echo ${MYMAP[baz]}
Deleting keys containing spaces
$ declare -A MYMAP
$ MYMAP[foo Z]=bar
$ echo ${MYMAP[foo Z]}
bar
$ unset MYMAP[foo Z] # WRONG
bash: unset: `MYMAP[foo': not a valid identifier
bash: unset: `Z]': not a valid identifier
$ unset MYMAP["foo Z"] # You must quote keys containing spaces when you unset in an associative array
$ echo ${MYMAP[foo Z]}
$ MYMAP[foo Z]=bar
$ unset MYMAP['foo Z'] # Single quotes work too
$ echo ${MYMAP[foo Z]}
$ MYMAP[baz A]=quux
$ echo ${MYMAP[baz A]}
quux
$ K="baz A"
$ unset MYMAP[$K] # WRONG
bash: unset: `MYMAP[baz': not a valid identifier
bash: unset: `A]': not a valid identifier
$ unset MYMAP["$K"] # You must quote variables whose values may contain spaces when you unset in an associative array
$ echo ${MYMAP[baz A]}
$ MYMAP[baz A]=quux
$ unset MYMAP['$K'] # Curiously, single quotes work here too, although I'd suggest avoiding them
$ echo ${MYMAP[baz A]}
Length
$ declare -A MYMAP=( [foo a]=bar [baz b]=quux )
$ echo ${#MYMAP[@]} # Number of keys in an associative array
2
$ echo $#MYMAP[@] # WRONG
0MYMAP[@]
$ echo ${#MYMAP} # WRONG
0
Numeric indexing
$ declare -A MYMAP=( [foo a]=bar [baz b]=quux )
$ KEYS=("${!MYMAP[@]}") # Make a normal array containing all the keys in the associative array
$ echo ${KEYS[0]} # Find a key via an index
foo a
$ echo ${MYMAP[${KEYS[0]}]} # Find a value via an index
bar
$ # Loop through using an index
$ for (( I=0; $I < ${#MYMAP[@]}; I+=1 )); do KEY=${KEYS[$I]}; echo $KEY --- ${MYMAP[$KEY]}; done
foo a --- bar
baz b --- quux
Scope
$ unset MYMAP
$ function createmap() { MYMAP[foo]=bar; } # Implicit creation puts it in the global scope
$ echo ${MYMAP[foo]}
$ createmap
$ echo ${MYMAP[foo]}
bar
$ unset MYMAP$ function createmaplocal() { declare -A MYMAP; MYMAP[foo]=bar; } # Explicit creation puts it in the local scope $ echo ${MYMAP[foo]}
$ createmaplocal $ echo ${MYMAP[foo]}
Checking Bash version
$ bash --version # Must be at least version 4 to have associative arrays GNU bash, version 4.2.24(1)-release (x86_64-pc-linux-gnu) ...