Shells with associative arrays
Some modern shells provide associative arrays: ksh93, bash ≥4, zsh. In ksh93 and bash, if a
is an associative array, then "${!a[@]}"
is the array of its keys:
for k in "${!a[@]}"; do
echo "$k -> ${a[$k]}"
done
In zsh, that syntax only works in ksh emulation mode. Otherwise you have to use zsh's native syntax:
for k in "${(@k)a}"; do
echo "$k -> $a[$k]"
done
${(k)a}
also works if a
does not have an empty key.
In zsh, you could also loop on both k
eys and v
alues at the same time:
for k v ("${(@kv)a}") echo "$k -> $v"
Shells without associative arrays
Emulating associative arrays in shells that don't have them is a lot more work. If you need associative arrays, it's probably time to bring in a bigger tool, such as ksh93 or Perl.
If you do need associative arrays in a mere POSIX shell, here's a way to simulate them, when keys are restricted to contain only the characters 0-9A-Z_a-z
(ASCII digits, letters and underscore). Under this assumption, keys can be used as part of variable names. The functions below act on an array identified by a naming prefix, the “stem”, which must not contain two consecutive underscores.
## ainit STEM
## Declare an empty associative array named STEM.
ainit () {
eval "__aa__${1}=' '"
}
## akeys STEM
## List the keys in the associatve array named STEM.
akeys () {
eval "echo \"\$__aa__${1}\""
}
## aget STEM KEY VAR
## Set VAR to the value of KEY in the associative array named STEM.
## If KEY is not present, unset VAR.
aget () {
eval "unset $3
case \$__aa__${1} in
*\" $2 \"*) $3=\$__aa__${1}__$2;;
esac"
}
## aset STEM KEY VALUE
## Set KEY to VALUE in the associative array named STEM.
aset () {
eval "__aa__${1}__${2}=\$3
case \$__aa__${1} in
*\" $2 \"*) :;;
*) __aa__${1}=\"\${__aa__${1}}$2 \";;
esac"
}
## aunset STEM KEY
## Remove KEY from the associative array named STEM.
aunset () {
eval "unset __aa__${1}__${2}
case \$__aa__${1} in
*\" $2 \"*) __aa__${1}=\"\${__aa__${1}%%* $2 } \${__aa__${1}#* $2 }\";;
esac"
}
(Warning, untested code. Error detection for syntactically invalid stems and keys is not provided.)
First, create an array with the parameters.
Then, store the array string value (found with declare -p
) at parameters
, and recover and use it as an actual array later on like in:
#!/bin/bash
programs=( "ls" "echo" )
declare -A parameters
arrayTmp=("-l" "/tmp/foo bar")
parameters["ls"]="`declare -p arrayTmp |sed -r "s,[^=]*='(.*)'$,\1,"`"
parameters["echo"]="Hello"
for program in "${programs[@]}";do
echo "PROGRAM: $program"
declare -a arrayTmp="${parameters[$program]}"
$program "${arrayTmp[@]}"
arrayTmp=()
done
Best Answer
The current bash manual on arrays says
So IMHO, you would have to do something different for associative arrays. I can't tell if this is a recent change in bash behavior.
Another way to define is_var_set would be to (ab)use the
declare
builtin, using the following:The above would work for top-level variable names, but not for any particular array elements.