在我的bash脚本中,我有两个数组。根据一些逻辑,其中一个或另一个将被使用,因此我会用变量varName
获取所需数组的名称。我可以确保使用以下代码获取该数组的值,但是否有方法获取其键?尝试了几个选项,但没有成功。
declare -A foo=([a]=b [c]=d)
declare -A bar=([e]=f [g]=h)
varName=foo
varArray=$varName[@]
echo ${!varArray}
感谢您。
在我的bash脚本中,我有两个数组。根据一些逻辑,其中一个或另一个将被使用,因此我会用变量varName
获取所需数组的名称。我可以确保使用以下代码获取该数组的值,但是否有方法获取其键?尝试了几个选项,但没有成功。
declare -A foo=([a]=b [c]=d)
declare -A bar=([e]=f [g]=h)
varName=foo
varArray=$varName[@]
echo ${!varArray}
不幸的是,如果不使用eval
,就无法实现。为了安全起见,请确保varName
只是一个有效标识符。
[[ varName =~ ^[a-zA-Z_][a-zA-Z_0-9]+$ ]] && eval "echo \${!$varName[@]}"
eval
是必要的,以便提供第二轮解析和评估。在第一轮中,Shell执行通常的参数扩展,结果是将字符串echo ${!foo[@]}
作为单个参数传递给eval
。(特别地,第一个美元符号被转义,因此被字面传递;$varName
被扩展为foo
;并且引号作为引号移除的一部分被删除。eval
然后解析并评估该字符串。
$ eval "echo \${!$varName[@]}"
# echo ${!foo [@]}
# The above is the argument that `eval` sees, after the shell
# does the normal evaluation before calling `eval`. Parameter
# expansion replaces $varName with foo and quote removal gets
# rid of the backslash before `$` and the double quotes.
a c
declare -n varName=foo
for key in "${!varName[@]}"; do
echo "$key"
done
有一种安全的IFS方法可以间接地获取数组的键(或值):
declare -a things=("an apple" "a banana")
declare -a tmp
arrayName=things
eval "tmp=(\"\${$arrayName[@]}\")"
# "${tmp[@]}" is now ("an apple" "a banana")
for
循环,对吧?那么选项就是通过IFS
传递它,或者还有更优雅的解决方案吗?再次感谢。 - user487772bash
4.2 或更早版本中是否能想到更好的解决方案。我刚刚想起来,在bash
4.3 中可以使用 nameref,如果可以的话。 - chepner