Bash 手册页描述了使用 来返回名称为(间接级别)${!a}
内容的变量的内容。a
我想知道如何使用它返回数组中的所有元素,即
a=(one two three)
echo ${a[*]}
回报
one two three
我想要:
b=a
echo ${!b[*]}
返回相同的。不幸的是,它没有,而是返回0
。
更新
鉴于答复,我现在意识到我的例子太简单了,因为当然,像这样:
b=("${a[@]}")
将会实现我所说的我需要的一切。
所以,这就是我的情况试去做:
LIST_lys=(lys1 lys2)
LIST_diaspar=(diaspar1 diaspar2)
whichone=$1 # 'lys' or 'diaspar'
_LIST=LIST_$whichone
LIST=${!_LIST[*]}
当然,仔细阅读 Bash 手册页会发现这不会按预期工作,因为最后一行只是返回“数组”的索引$_LIST
(根本不是数组)。
无论如何,以下内容应该可以完成工作(如所指出的):
LIST=($(eval echo \${$_LIST[*]}))
或...(我最终走的路线):
LIST_lys="lys1 lys2"
...
LIST=(${!_LIST})
当然,假设元素不包含空格。
答案1
我认为 bash 变量的间接引用的使用应该按字面意思对待。
例如。对于你原来的例子:
a=(one two three)
echo ${a[*]} # one two three
b=a
echo ${!b[*]} # this would not work, because this notation
# gives the indices of the variable b which
# is a string in this case and could be thought
# as a array that conatins only one element, so
# we get 0 which means the first element
c='a[*]'
echo ${!c} # this will do exactly what you want in the first
# place
对于最后一个真实场景,我相信下面的代码可以完成工作。
LIST_lys=(lys1 lys2)
LIST_diaspar=(diaspar1 diaspar2)
whichone=$1 # 'lys' or 'diaspar'
_LIST="LIST_$whichone"[*]
LIST=( "${!_LIST}" ) # Of course for indexed array only
# and not a sparse one
最好使用"${var[@]}"
避免混淆$IFS
和 参数扩展的符号。这是最终的代码。
LIST_lys=(lys1 lys2)
LIST_diaspar=(diaspar1 diaspar2)
whichone=$1 # 'lys' or 'diaspar'
_LIST="LIST_$whichone"[@]
LIST=( "${!_LIST}" ) # Of course for indexed array only
# and not a sparse one
# It is essential to have ${!_LIST} quoted
答案2
您需要显式复制元素。对于索引数组:
b=("${a[@]}")
对于关联数组(注意a
是数组变量的名称,而不是其值为数组变量名称的变量):
typeset -A b
for k in "${!a[@]}"; do b[$k]=${a[$k]}; done
如果数组中有变量名称,则可以使用逐元素方法以及额外的步骤来检索键。
eval "keys=(\"\${!$name[@]}\")"
for k in "${keys[@]}"; do eval "b[\$k]=\${$name[\$k]}"; done
(警告,本文中的代码是直接在浏览器中输入的,未经测试。)
答案3
${!b[*]}
扩展到 array 中使用的索引b
。
您想要的必须分两步完成,因此eval
会有所帮助:eval echo \${$b[*]}
。 (请注意,它\
确保第一个$
将通过第一步,即变量扩展,并且仅在第二步中通过 进行扩展eval
。)
根据参数扩展,!
两者都用于间接扩展 ( {!a}
)、匹配前缀的名称 ( ${!a*}
) 和数组键列表 ( ${!a[*]}
)。由于数组键列表与预期的间接扩展+数组元素扩展具有相同的语法,因此不支持后者。
答案4
要间接访问数组,只需添加[@]
到间接变量b=a[@]
。
如果设置了该变量:
a=(one two three)
printf '<%s> ' "${a[@]}"; echo
然后,这将起作用:
b="a[@]"
printf '<%s> ' "${!b}"
或者简单地:
echo "${!b}"
这样的数组可以复制如下:
newArr=( "${!b}" )
然后打印:
declare -p newArr
在一个脚本中:
#!/bin/bash
a=(one two three)
echo "original array"
printf '<%s> ' "${a[@]}"; echo
echo "Indirect array with variable b=a[@]"
b="a[@]"
printf '<%s> ' "${!b}"; echo
echo "New array copied in newArr, printed with declare"
newArr=( "${!b}" )
declare -p newArr
当然,以上所有操作都会复制一个非稀疏数组。所有索引都有值的一种。
稀疏数组
稀疏数组是一种可能包含未定义元素的数组。
例如a[8]=1234
定义一个元素,而在bash中,0到7不存在。
要复制此类稀疏数组,请使用此方法
打印旧数组:
$ oldarr[8]=1234 $ declare -p oldarr declare -a oldarr=([8]="1234")
替换数组的名称并捕获字符串:
$ str=$(declare -p oldarr | sed 's/oldarr=/newarr=/')
评估如此创建的字符串,新数组已被定义:
$ eval "$str" $ declare -p newarr declare -a newarr=([8]="1234")