我正在编写Bash脚本,以简化从主站点到多个代理商的文件副本。 在这个脚本中,我尝试使用变量作为关联数组名称,但我得到了一个错误,这里是代码:
#!/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
这是错误:
./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
我想做的是什么? 提前谢谢。
答案 0 :(得分:1)
这是可能的,但除非你有bash v4.3
,否则这并不容易。使用4.3,您可以使用“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
好的,你可能还没有bash 4.3但是将来上面对某人有用。所以没有它,你可以遵循你提出的策略,即复制指示的关联数组。如果阵列不大,那也不算太糟糕。为此,请使用上述内容,但将nameref行(declare -n ARRAY=$group
)替换为以下内容:
defn=$(declare -p $group)
eval "${defn/$group/ARRAY}"
unset defn
在这种情况下,您将使用替代测试来获得成功。
注意:对bash
变量名称使用全部大写真的不是一个好主意。惯例是系统生成的环境变量和shell内置变量使用全部大写。用户变量应该是低级的,以免与这些预定义的变量发生冲突。