3

I have a few different associative arrays as variables:

declare -A FIRST=( [hello]=world [foo]=bar )
declare -A SECOND=( [bonjour]=monde [fu]=ba )

What I'd like to be able to do is take a third variable and assign it to one or the other, something like:

usethisarray=$FIRST

or maybe

declare -a usethisarray=$FIRST

But neither of those really work. Can I get a level of indirection to point at the associative array I need?

perreal
  • 94,503
  • 21
  • 155
  • 181
maxst
  • 145
  • 1
  • 1
  • 5

5 Answers5

6

Note to readers: this answer is from 2013. You should now be using @ryenus's answer.


bash has variable indirection but it's kind of a pain to use:

$ declare -A FIRST=( [hello]=world [foo]=bar )
$ alias=FIRST
$ echo "${!alias[foo]}"

$ item=${alias}[foo]
$ echo ${!item}
bar
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • That's it, that's what I was looking for. And you're right, it is kind of a pain to use. Sigh... – maxst Jun 14 '13 at 00:25
  • 1
    This is not really the right answer, you need a **nameref**, see [the other answer](https://stackoverflow.com/a/70070402/537554/): https://stackoverflow.com/a/70070402/537554 – ryenus Nov 22 '21 at 18:06
  • In my defence, namerefs were a pretty new feature in 2013. – glenn jackman Nov 22 '21 at 18:12
3

The answer is yes, and the reference variable needs to be a nameref for it to be used with arrays:

declare -A FIRST=( [hello]=world [foo]=bar )
declare -A SECOND=( [bonjour]=monde [fu]=ba )

#### ordinary variable assignment does NOT work
declare any_var=FIRST
echo -e '${any_var[@]}:' "${any_var[@]}"
echo -e '${!any_var[@]}:' "${!any_var[@]}"
echo -e '${#any_var[@]}:' "${#any_var[@]}"

#### nameref works, via 'declare -n' or 'local -n'
declare -n arr_ref=SECOND
echo '${arr_ref[@]}:' "${arr_ref[@]}"
echo '${!arr_ref[@]}:' "${!arr_ref[@]}"
echo '${#arr_ref[@]}:' "${#arr_ref[@]}"

The result:

ordinary variable assignment does NOT work

${any_var[@]}: FIRST
${!any_var[@]}: 0
${#any_var[@]}: 1

nameref works, via 'declare -n' or 'local -n'

${arr_ref[@]}: monde ba     # values of the associative array / map
${!arr_ref[@]}: bonjour fu  # keys of the associative array / map
${#arr_ref[@]}: 2           # size of the associative array / map

See https://www.gnu.org/software/bash/manual/bash.html#Shell-Parameters

Array variables cannot be given the nameref attribute. However, nameref variables can reference array variables and subscripted array variables.

Meanwhile, variable indirection, or more correctly indirect expansion, which also uses the exclamation point (!), it requires the variable or parameter to be NOT a nameref:

If the first character of parameter is an exclamation point (!), and parameter is not a nameref, it introduces a level of indirection.

ryenus
  • 15,711
  • 5
  • 56
  • 63
1

I think this is the only way:

#!/bin/bash
declare -A FIRST=( [hello]=world [foo]=bar )
declare -A SECOND=( [bonjour]=monde [fu]=ba )
declare -A usethisarray
for key in ${!FIRST[@]}; do
    usethisarray["$key"]="${FIRST["$key"]}"
done
echo ${usethisarray[hello]}
echo ${usethisarray[foo]}
perreal
  • 94,503
  • 21
  • 155
  • 181
0

I think this is what you mean:

[bob in ~] ARRAY=(one two three)

[bob in ~] echo ${ARRAY[*]} one two three

[bob in ~] echo $ARRAY[] one[]

[bob in ~] echo ${ARRAY[2]} three

[bob in ~] ARRAY[3]=four

[bob in ~] echo ${ARRAY[*]} one two three four

Reference below:

See the link for more information: http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_10_02.html

Liam Sorsby
  • 2,912
  • 3
  • 28
  • 51
  • Sorry also try this link. More to do with what you was asking. http://stackoverflow.com/questions/6660010/bash-how-to-assign-an-associative-array-to-another-variable-name-e-g-rename-t – Liam Sorsby Jun 14 '13 at 00:04
  • The text isn't really what I was looking for, as that's just standard array manipulation. The other stackoverflow link is a little closer, as it talks about renaming an associate array. What I need is a way to indirectly reference the correct associate array (my script has a few different ones). I want to be able to set a variable to reference/copy the correct one when needed. – maxst Jun 14 '13 at 00:09
  • This has an example in direct reference to arrays: http://stackoverflow.com/questions/11180714/how-to-iterate-over-an-array-using-indirect-reference – Liam Sorsby Jun 14 '13 at 00:15
0

String Variable Indirection

ARRAY=([a]=1 [b]=2 [c]=3)

name="ARRAY"

eval a=\${$name['a']}

eval b=\${$name['b']}

eval c=\${$name['c']}

echo "$a$b$c"

Output>>> 123

eval $array['a']=10             

echo ${ARRAY['a']}


Output>>> 10
Matheus Cuba
  • 2,068
  • 1
  • 20
  • 31
sean
  • 31
  • 4