Skip to content

Instantly share code, notes, and snippets.

@sh78
Last active April 18, 2018 02:30
Show Gist options
  • Save sh78/70612d2053954d672457 to your computer and use it in GitHub Desktop.
Save sh78/70612d2053954d672457 to your computer and use it in GitHub Desktop.
# credit to http://www.artificialworlds.net/blog/2012/10/17/bash-associative-array-examples/
# 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
# 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
# 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
# =>
# 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)
# => ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment