Skip to main content
1 of 5
drwatsoncode
  • 293
  • 1
  • 3
  • 9

Count number of elements in bash array, where the name of the array is dynamic (i.e. stored in a variable)

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!

drwatsoncode
  • 293
  • 1
  • 3
  • 9