The modern (bash 4.3+) approach uses "namevars", a facility borrowed from ksh:
for _count_var in "${!count_@}"; do
declare -n count=$_count_var # make count an alias for $_count_var
for key in "${!count[@]}"; do # iterate over keys, via same
echo "$key occurred ${count[$key]} times" # extract value, likewise
done
unset -n count # clear that alias
done
declare -n count=$count_var
allows "${count[foo]}"
to be used to look up item foo
in the associative array named count_var
; similarly, count[foo]=bar
will assign to that same item. unset -n count
then removes this mapping.
Prior to bash 4.3:
for _count_var in "${!count_@}"; do
printf -v cmd '_count_keys=( "${!%q[@]}" )' "$_count_var" && eval "$cmd"
for key in "${_count_keys[@]}"; do
var="$_count_var[$key]"
echo "$key occurred ${!var} times"
done
done
Note the use of %q
, rather than substituting a variable name directly into a string, to generate the command to eval
. Even though in this case we're probably safe (because the set of possible variable names is restricted), following this practice reduces the amount of context that needs to be considered to determine whether an indirect expansion is secure.
In both cases, note that internal variables (_count_var
, _count_keys
, etc) use names that don't match the count_*
pattern.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…