I've got a variable list of associative arrays that I want to iterate through and retrieve their key/value pairs.
I iterate through a single associative array by listing all its keys and getting the values, ie.
for key in "${!queue1[@]}" do
echo "key : $key"
echo "value : ${queue1[$key]}"
done
The tricky part is that the names of the associative arrays are variable variables, e.g. given count = 5, the associative arrays would be named queue1, queue2, queue3, queue4, queue5.
I'm trying to replace the sequence above based on a count, but so far every combination of parentheses and eval has not yielded much more then bad substitution errors. e.g below:
for count in {1,2,3,4,5} do
for key in "${!queue${count}[@]}" do
echo "key : $key"
echo "value : ${queue${count}[$key]}"
done
done
Help would be very much appreciated!
The difficulty here stems from the fact that the syntax for indirect expansion (${!nameref}) clashes with the syntax for extracting keys from an associative arrays (${!array[@]}). We can have only one or the other, not both.
Wary as I am about using eval, I cannot see a way around using it to extract the keys of an indirectly referenced associative array:
keyref="queue${count}[@]"
for key in $(eval echo '${!'$keyref'}'); do ... ; done
You can however avoid eval and use indirect expansion when extracting a value from an array given the key. Do note that the [key] suffix must be part of the expansion:
valref="queue${count}[$key]"
echo ${!valref}
To put this in context:
for count in {1..5} ; do
keyref="queue${count}[@]"
for key in $(eval echo '${!'$keyref'}'); do
valref="queue${count}[$key]"
echo "key = $key"
echo "value = ${!valref}"
done
done
I was able to make it work with the following script:
for count in {1..5} ; do
for key in $(eval echo '${!q'$count'[@]}') ; do
eval echo '${q'$count"[$key]}"
done
done
Note it breaks if any key contained a space. If you want to deal with complex data structures, use a more powerful language like Perl.
I think this might work (but untested). The key is to treat the indexing
as the full name of a variable. (That is, the array queue5 can be
treated as a sequence of variables named queue5[this], queue5[that], etc.)
for count in {1,2,3,4,5} do
assoc="queue$count[@]"
for key in "${!assoc}" do
echo "key : $key"
val="queue$count[$key]"
echo "value : ${!val}"
done
done
来源:https://stackoverflow.com/questions/13305717/bash-scripting-iterating-through-variable-variable-names-for-a-list-of-assoc