我需要在 bash 脚本中调用一个数组,该数组的名称由字符串变量定义,如下所示:
var="array"
array=(
1
2
3
)
$var 将始终等于数组的名称
#failed attempts at echoing ${array[@]}
echo "${!var} # returns only the first value of the array
echo "${!var[@]}" # returns 0
tempvar='${'$var'[@]}' # makes a new variable with value of "${array[@]}"
echo "${!tempvar}" #returns 'invalid variable name'
我对此很陌生,没有找到解决这个问题的方法。先感谢您。
答案1
bash 特定的
要引用数组,请使用“nameref”declare -n
array=(1 2 3)
var=array
declare -n a=$var
for idx in "${!a[@]}"; do echo "$idx -> ${a[idx]}"; done
a[4]="hello"
declare -p a array # original altered by above assignment
输出
0 -> 1
1 -> 2
2 -> 3
declare -n a="array"
declare -a array=([0]="1" [1]="2" [2]="3" [4]="hello")
做一个复制在数组中,使用间接变量:这很难看
tmp=${var}[@] # constructing a string
b=( "${!tmp}" ) # indirect variable expansion
b[4]="goodbye"
declare -p tmp b array # original not changed
输出
declare -- tmp="array[@]"
declare -a b=([0]="1" [1]="2" [2]="3" [3]="hello" [4]="goodbye")
declare -a array=([0]="1" [1]="2" [2]="3" [4]="hello")
注意“hello”元素的索引是如何变化的b
:这是因为b=("${!tmp}")
唯一创建了数组的副本元素,不是指数。
答案2
请注意,在 bash 中(就像在 ksh 中,bash 复制了其数组设计),数组与普通数组不同,但稀疏数组所以更像是键仅限于正整数的关联数组。
在这里,您可以执行以下操作:
$ array=( [12]=a [23]=b [34]=c )
$ var=array
$ tempvar_for_separated_out_keys='!'$var[@]
$ tempvar_for_separated_out_values=$var[@]
$ printf -- '- <%s>\n' "${!tempvar_for_separated_out_keys}"
bash: !array[@]: invalid variable name
$ printf -- '- <%s>\n' "${!tempvar_for_separated_out_values}"
- <a>
- <b>
- <c>
(是的,钥匙的那个还不能用)。
或者您可以使用 nameref 代替(也来自 ksh,但有一些差异)。
$ typeset -n var=array
$ printf -- '- <%s>\n' "${!var[@]}"
- <12>
- <23>
- <34>
$ printf -- '- <%s>\n' "${var[@]}"
- <a>
- <b>
- <c>
或者您可以切换到zsh
,其中使用参数扩展标志完成取消引用P
。zsh
数组就是数组,尽管它也有适当的关联数组,其键为任意字符串(任何字节或字符)。
$ array=( a b c '' ) var=array
$ printf -- '- <%s>\n' ${(P)var}
- <a>
- <b>
- <c>
$ printf -- '- <%s>\n' "${(P@)var}"
- <a>
- <b>
- <c>
- <>
$ typeset -A hash=( 12 a 23 b 34 c '' empty )
$ var=hash
$ printf -- '- <%s>\n' "${(Pk@)var}"
- <>
- <34>
- <23>
- <12>
$ printf -- '- <%s>\n' "${(Pv@)var}"
- <empty>
- <c>
- <b>
- <a>
$ printf -- '- <%s> -> <%s>\n' "${(Pkv@)var}"
- <> -> <empty>
- <34> -> <c>
- <23> -> <b>
- <12> -> <a>
(k
标志为键,v
标志为价值观(默认),@
在引号内标记以保留空元素,如 Bourne shell 的"$@"
)。