Bash 4.1.2如何从动态引用的关联数组中获取指定键值
在Bash 4.1.2中动态引用关联数组的解决方案
问题背景
GNU Bash 4.1.2版本不支持declare -n(命名引用)特性,当尝试通过存储数组名称的变量动态获取关联数组的键值时,会触发bad substitution错误。
正常取值示例
直接使用关联数组名称可以正常获取对应键的值:
declare -rA DBONE=([system_name]='ABC' [dbname]='abc_database' [dbusername]='user1') declare -rA DBTWO=([system_name]='DEF' [dbname]='def_database' [dbusername]='user2') declare -rA DBTHREE=([system_name]='XYZ' [dbname]='xyz_database' [dbusername]='user3') # 直接使用数组名称取值 echo ${DBTWO["dbname"]}
输出:def_database(结果正确)
错误示例及原因
尝试通过变量间接引用关联数组时,错误的写法会导致语法报错:
declare -rA DBONE=([system_name]='ABC' [dbname]='abc_database' [dbusername]='user1') declare -rA DBTWO=([system_name]='DEF' [dbname]='def_database' [dbusername]='user2') declare -rA DBTHREE=([system_name]='XYZ' [dbname]='xyz_database' [dbusername]='user3') # 存储数组名称的数组 declare -a databases=(DBONE DBTWO DBTHREE) # 获取第一个数组名称 database="${databases[0]}" echo "The dbname is ${$database[dbname]}" echo "The dbname is ${$database}[dbname]"
输出:
./myscript.sh: ${$database[dbname]}: bad substitution ./myscript.sh: ${$database}[dbname]: bad substitution
原因:Bash 4.1.2不支持${$variable}这种嵌套变量替换语法,且没有命名引用特性来简化动态数组引用。
遍历动态数组的解决方案
针对遍历存储数组名称的数组这一需求,可使用间接扩展特性实现,无需依赖declare -n:
declare -rA DBONE=([system_name]='ABC' [dbname]='abc_database' [dbusername]='user1') declare -rA DBTWO=([system_name]='DEF' [dbname]='def_database' [dbusername]='user2') declare -rA DBTHREE=([system_name]='XYZ' [dbname]='xyz_database' [dbusername]='user3') declare -a databases=(DBONE DBTWO DBTHREE) for db in "${databases[@]}"; do # 构造关联数组的引用字符串 ref="$db[dbname]" # 使用间接扩展获取对应键的值 dbname="${!ref}" echo "The database is $db, and the dbname is $dbname" done
输出:
The database is DBONE, and the dbname is abc_database The database is DBTWO, and the dbname is def_database The database is DBTHREE, and the dbname is xyz_database
也可以使用eval实现(注意:使用eval时需确保变量内容安全,避免注入风险):
declare -rA DBONE=([system_name]='ABC' [dbname]='abc_database' [dbusername]='user1') declare -rA DBTWO=([system_name]='DEF' [dbname]='def_database' [dbusername]='user2') declare -rA DBTHREE=([system_name]='XYZ' [dbname]='xyz_database' [dbusername]='user3') declare -a databases=(DBONE DBTWO DBTHREE) for db in "${databases[@]}"; do eval dbname=\"\${$db[dbname]}\" echo "The database is $db, and the dbname is $dbname" done
内容的提问来源于stack exchange,提问作者Genki
相关产品推荐
相关产品推荐

