With recent versions of bash, you could use namerefs:
arrLen() {
typeset -n __Var="$1"
echo "${#__Var[@]}"
}
Here we choose __Var
as the nameref variable name, as one that is unlikely to be used otherwise within your script. arrLen __Var
fails with circular name reference
errors.
Namerefs (like typeset
, and bash's array design in general) is a feature that bash borrowed from the Korn shell. In ksh (ksh93 where namerefs were introduced), you'd write:
function arrLen {
typeset -n var="$1"
echo "${#var[@]}"
}
(ksh namerefs are able to reference a variable with the same name from the caller's scope (or the global scope), but scoping (static scoping) is only done in functions declared with the Korn syntax, not with the Bourne syntax)
Or you can always use eval
to construct code dynamically.
arrLen() {
eval 'echo "${#'"$1"'[@]}"'
}
With zsh
:
arrLen() echo ${(P)#1}
bash Nameref resolution, zsh's P
parameter expansion flag also do some form of eval
(dynamic code evaluation) under the hood, so all those approaches are equally unsafe if the argument passed to arrLen
is not guaranteed to be a valid variable name, but equally safe if they are.
${#$1[@]}
doesn't work? – ilkkachu Aug 15 '22 at 12:27