我想将数组传递给 bash 函数,但出现bad substitution
错误
例子
mapfile -t ray < <(parallel -j 0 echo ::: {1..10})
declare -p ray
declare -a ray=([0]="2" [1]="1" [2]="3" [3]="4" [4]="5" [5]="6" [6]="7" [7]="8" [8]="9" [9]="10")
arrLen() {
echo "${#$1[@]}"
}
arrLen ray
-bash: ${#$1[@]}: bad substitution
那么是否不可能将参数传递给 bash 数组呢?
答案1
对于最新版本的 bash,您可以使用 namerefs:
arrLen() {
typeset -n __Var="$1"
echo "${#__Var[@]}"
}
在这里,我们选择__Var
作为 nameref 变量名称,因为它不太可能在脚本中以其他方式使用。arrLen __Var
因错误而失败circular name reference
。
Namerefs(就像typeset
一般的 、 和 bash 的数组设计)是 bash 从 Korn shell 借用的一个功能。在 ksh(引入 namerefs 的 ksh93)中,您可以编写:
function arrLen {
typeset -n var="$1"
echo "${#var[@]}"
}
(ksh namerefs 能够从调用者的作用域(或全局作用域)引用具有相同名称的变量,但作用域(静态作用域)仅在使用 Korn 语法声明的函数中完成,而不是在使用 Bourne 语法声明的函数中完成)
或者您始终可以使用eval
动态构造代码。
arrLen() {
eval 'echo "${#'"$1"'[@]}"'
}
和zsh
:
arrLen() echo ${(P)#1}
bash Nameref 解析,zsh 的P
参数扩展标志也在eval
后台执行某种形式的(动态代码评估),因此如果传递给的参数arrLen
不能保证是有效的变量名,则所有这些方法都同样不安全,但如果它们是有效的变量名,则同样安全。