Bash : Use a variable as an associative array name

匿名 (未验证) 提交于 2019-12-03 09:14:57

问题:

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.



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