通过将其名称作为变量引用来检索 bash 数组

通过将其名称作为变量引用来检索 bash 数组

我需要有关 bash 扩展的帮助。
我想检索数组值,GNU bash 5.1.0。数组名称应该是一个变量。 “只是”引用 bash 中的变量。

我有一个名为“armin”的数组,其名称位于变量 $gral 中(工作正常):

gral="armin"

赋值:

declare -a ${gral}[1]="milk"
declare -a ${gral}[2]="cow"
declare  ${gral}[7]="budgie"
declare  ${gral}[9]="pla9ne"

美好的。

数组存在:

$ echo ${armin[@]}
milk cow budgie pla9ne

数组索引存在:

$echo ${!armin[@]}
1 2 7 9

数组和索引都很好。

我想通过引用它来检索数组名称作为变量,而不是手动。有很多...
变量之前已设置和使用:

$ echo $gral
armin  ## name of our bash array

很好——到目前为止。

只是为了显示差异而不使用变量:

echo ${armin[@]}
milk cow budgie pla9ne

现在尝试引用变量(gral)来调用名称(armin):

$ echo ${$gral[@]}
-bash: ${$gral[@]}: wrong substitution.

$echo ${"$gral"[@]}
-bash: ${"$gral"[@]}: wrong substitution.
echo ${"gral"[@]}
-bash: ${"gral"[@]}: wrong substitution.
echo ${${gral}[@]}
-bash: ${${gral}[@]}: wrong substitution.

全部失败。也尝试了“eval”。使用关联(声明 -A)没有什么区别。

备注:索引以这种方式工作正常,没有问题。名字是问题。

我想我错过了一些东西。也许答案之前已经描述过,我发现了很多关于数组中的变量的有趣的东西,但没有识别出我的挑战的答案。

你可以吗请帮我找到通过将数组名称引用为变量来检索数组的术语

答案1

使用 namerefs(在 Bash >= 4.3 中):

$ armin=(foo bar doo)
$ declare -n gral=armin      # 'gral' references array 'armin'  
$ gral[123]=quux             # same as 'armin[123]=quux'
$ echo "${gral[@]}"
foo bar doo quux
$ echo "${gral[1]}"
bar
$ echo "${!gral[@]}"         # listing the indexes works too
0 1 2 123

也可以看看:bash 是否支持使用指针?

答案2

正如@ilkkachu 的回答,namerefs 是这里使用的工具。它们使得将数组传递给函数变得非常容易。例如:

dumpArray() {
  local -n ary=$1
  for i in "${!ary[@]}"; do
    printf "%s\t%s\n" "$i" "${ary[$i]}"
  done
}

该函数可以处理数组和关联数组:

$ declare -a armin=([1]=milk [2]=cow [7]=bugle [9]=pla9ne)

$ dumpArray armin
1   milk
2   cow
7   bugle
9   pla9ne

$ declare -A map=([foo]=bar [baz]=qux)

$ dumpArray map
foo bar
baz qux

唯一真正的问题是,让 nameref 引用同名的数组会很混乱:

$ ary=(a b c)

$ dumpArray ary
bash: local: warning: ary: circular name reference
bash: warning: ary: circular name reference
bash: warning: ary: circular name reference
bash: warning: ary: circular name reference
bash: warning: ary: circular name reference
0   a
bash: warning: ary: circular name reference
bash: warning: ary: circular name reference
1   b
bash: warning: ary: circular name reference
bash: warning: ary: circular name reference
2   c

所以在函数中,你让数组有一个奇怪的名字,比如

dumpArray() {
  local -n __dumpArray_ary=$1
  do_stuff_with "${__dumpArray_ary[@]}"
}

答案3

[@]在包含名称的变量中包含“索引”,即:

ref=$gral'[@]'
printf '%s\n' "${!ref}"

输出:

milk
cow
budgie
pla9ne

它也适用于包含空格的值。

答案4

好吧,
答案是通过作为变量传递的名称取消引用数组(部分类似于指针)
是(重复使用上面的示例):

eval echo "\$$(eval echo "{$gral[@]}")"
$gral 保存数组名称

结果:

奶牛虎皮鹦鹉 pla9ne

您现在可以扩展此解决方案以使用索引条目迭代 bash 数组(索引和关联)内容。

很高兴我找到了答案。感谢大家的帮助!

访问变量内容的内容。

在abs-guide中有导致结果的提示:
https://tldp.org/LDP/abs/html/abs-guide.html#IVR

感谢孟德尔·库珀 (Mendel Cooper) 的贡献;非常感谢我们有这份伟大的礼物,名为高级 Bash 脚本指南

好吧,
出于安全考虑,评估很难看。
尝试找到一个更好的...

相关内容