Indirect return of all elements in an array

You need to copy the elements explicitly. For an indexed array:

b=("${a[@]}")

For an associative array (note that a is the name of the array variable, not a variable whose value is the name of an array variable):

typeset -A b
for k in "${!a[@]}"; do b[$k]=${a[$k]}; done

If you have the variable name in an array, you can use the element-by-element method with an extra step to retrieve the keys.

eval "keys=(\"\${!$name[@]}\")"
for k in "${keys[@]}"; do eval "b[\$k]=\${$name[\$k]}"; done

(Warning, the code in this post was typed directly in a browser and not tested.)


I think the use of indirect reference of bash variable should be treated literally.

Eg. For your original example:

a=(one two three)
echo ${a[*]} # one two three
b=a
echo ${!b[*]} # this would not work, because this notation 
              # gives the indices of the variable b which
              # is a string in this case and could be thought
              # as a array that conatins only one element, so
              # we get 0 which means the first element
c='a[*]'
echo ${!c} # this will do exactly what you want in the first
           # place

For the last real scenario, I believe the code below would do the work.

LIST_lys=(lys1 lys2)
LIST_diaspar=(diaspar1 diaspar2)

whichone=$1   # 'lys' or 'diaspar'

_LIST="LIST_$whichone"[*]
LIST=( "${!_LIST}" ) # Of course for indexed array only 
                     # and not a sparse one

It is better to use notation "${var[@]}" which avoid messing up with the $IFS and parameter expansion. Here is the final code.

LIST_lys=(lys1 lys2)
LIST_diaspar=(diaspar1 diaspar2)

whichone=$1   # 'lys' or 'diaspar'

_LIST="LIST_$whichone"[@]
LIST=( "${!_LIST}" ) # Of course for indexed array only 
                     # and not a sparse one
                     # It is essential to have ${!_LIST} quoted

${!b[*]} expands to the indices used in array b.

What you would like has to be done in two steps, so eval will help: eval echo \${$b[*]}. (Note the \ which ensures that the first $ will pass the first step, the variable expansion, and will be only expanded in the second step by eval.)

According to Parameter Expansion ! is both used for indirect expansion ({!a}), Names matching prefix (${!a*}) and List of array keys (${!a[*]}). Because List of array keys has the same syntax as your intended indirect expansion+array element expansion, the later is not supported as is.

Tags:

Bash

Array