Bash : Use a variable as an associative array name

醉酒当歌 提交于 2020-01-02 09:39:26

问题


I'm writing a Bash script to simplify file copies from our main site to multiple agencies. In this script, I'm trying to use a variable as an associative array name but I optain an error, here is the code :

#!/bin/bash

declare -A GROUP1
declare -A GROUP2
declare -A GROUP3
declare -A ARRAY

GROUP1["SITE1"]="x.x.x.x"
GROUP1["SITE2"]="y.y.y.y"
GROUP1["SITE3"]="z.z.z.z"

GROUP2["SITE1"]="1.1.1.1"
GROUP2["SITE2"]="2.2.2.2"
GROUP2["SITE3"]="3.3.3.3"

GROUP2["SITE1"]="a.a.a.a"
GROUP2["SITE2"]="b.b.b.b"
GROUP2["SITE3"]="c.c.c.c"

read -p "Choose a group of sites : " group

case $group in
    1 ) DEST="GROUP1" ;;
    2 ) DEST="GROUP2" ;;
    3 ) DEST="GROUP3" ;;
esac

eval "ARRAY=(\${$DEST[@]})"

for elem in "${!ARRAY[@]}"
do
   echo $elem
   echo ${ARRAY[$elem]}
done

Here is the error :

./test: line28: TAB : 3.3.3.3 : must use subscript when assigning associative array
./test: line28: TAB : 2.2.2.2 : must use subscript when assigning associative array
./test: line28: TAB : 1.1.1.1 : must use subscript when assigning associative array

Is what I am trying to do possible ? Thanks in advance.


回答1:


It's possible but it's not easy unless you have bash v4.3. With 4.3, you can use a "nameref":

declare -A GROUP1
declare -A GROUP2
declare -A GROUP3

GROUP1["SITE1"]="x.x.x.x"
#...

# Yuk. Use command-line options, not stdin
read -p "Choose a group of sites : " group

for g in GROUP1 GROUP2 GROUP3; do if [[ $group == $g ]]; then

  # Here's the nameref: After this executes, ARRAY is an alias for
  # the indicated variable.
  declare -n ARRAY=$group
  break

fi

### This is documented but might not work depending on bash version
### Instead you could test for existence of a known key:
###    if [[ ! -v ${ARRAY[SITE1]} ]]; then
if [[ ! -R ARRAY ]]; then
 echo "No such group" >> /dev/stderr; exit 1
fi

OK, you probably don't yet have bash 4.3 but in the future the above will be useful to someone. So without it, you could follow a strategy like the one which you propose, which is to copy the indicated associative array. That's not too bad if the arrays aren't big. To do that, use the above but replace the nameref line (declare -n ARRAY=$group) with the following:

defn=$(declare -p $group)
eval "${defn/$group/ARRAY}"
unset defn

In this case, you'll have the use the alternative test for success.


Note: It's really not a good idea to use all caps for bash variable names. The convention is that system-generated environment variables and shell builtin variables use all caps. User variables should be lower-cased in order to not collide with these predefined variables.



来源:https://stackoverflow.com/questions/25767413/bash-use-a-variable-as-an-associative-array-name

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!