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) ...