Using bash parameter substitution, one can do the following:
- Determine the length of an array:
myArr=(A B C); echo ${#myArr}. - Indirectly reference a variable by name:
NAME=myVar; echo ${!NAME}
(this also applies to array elements):
NAME=myArr[1]; echo ${!NAME}
But if the name of an array is stored in another variable, how can one determine the number of elements in the array? (One might consider this a combination of the above two parameter substitutions.) Preferably I would like to do this without making a full copy of the array or using eval.
For example:
myArr=(A B C D)
NAME=myArr
# Get the number of elements in the array indirectly referenced by NAME.
count=${#$NAME[@]} # This syntax is invalid. What is the right way?
Below are multiple attempts that all FAIL:
# Setup for following attempts:
myArr=(A B C D)
NAME=myArr
EXPR1=$NAME[@] # i.e. EXPR1='myArr[@]'
EXPR2=#$NAME[@] # i.e. EXPR2='#myArr[@]'
# Failed attempts to get the lengh of the array indirectly:
1. count=${#$NAME[@]} # ERROR: bash: ...: bad substitution
2. count=${#!EXPR1} # ERROR: bash: !EXPR}: event not found
3. count=${#\!EXPR1} # ERROR: bash: ...: bad substitution
4. count=${!#EXPR1} # ERROR: bash: ...: bad substitution
5. count=${!EXPR2} # Returns NULL
I've also tried some other variants of the above, but have not yet found anything that works without either: (A) making a copy of the array or (B) by using eval.
The latter two methods are discussed below.
##Working Methods: There are a couple ways of solving this that are probably not optimal (but correct me if I'm wrong):
Method 1: Copy the Array
Assign the array to another (statically-named) variable and get the number of elements in it.
EXPR=$NAME[@]
arrCopy=( "${!$EXPR}" )
count=${#arrCopy}
Method 2: Use eval
EXPR="count=\${#$NAME[@]}" # i.e. 'count=${myArr[@]}'
eval $EXPR
# Now count is set to the length of the array
##Summary:
Is there any built-in method (i.e. parameter substitution syntax) in bash to determine the length of an array indirectly? If not, what is the most efficient way to do this? I assume it is the eval method above, but are there security or performance issues with eval?
Thanks!