根据字符串的值调用数组

根据字符串的值调用数组

我需要在 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,其中使用参数扩展标志完成取消引用Pzsh数组就是数组,尽管它也有适当的关联数组,其键为任意字符串(任何字节或字符)。

$ 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 的"$@")。

相关内容