2

I found a similar question here, but it does not seem to be identical, and none of the answers provide the output that I want. I have an array, for which I want to find how many elements it contains by accessing it using dynamically generated name.

declare -a array0=(2 4 2 5) # contains 4 values indx=0 Name="array$indx" # create a name reference => array0 # I know how to obtain an indexed value by INDIRECT reference: val0=${!Name[0]} # I also know how to get array length using DIRECT name len=${#array0[@]} 

What I need is find the number of elements of the array0 by referencing it using variable Name

len=${#!Name[@]} # the syntax is incorrect 

Any suggestions for implementation?

EDIT:
I was wrong about being able to access the array entries using this:

val0=${!Name[0]} 

It only works for indx=0, so if I wanted to get other entries from the array, it simply returns an empty string:

val4=${!Name[4]} #does not work 

or

i=4 val4=${!Name[$i]} # does not work 
1

2 Answers 2

4

With bash-4.3 or above, you can use namerefs:

a0=(a b c) i=0 typeset -n Name="a$i" echo "${#Name[@]}" 

or you can always use eval. In any case, don't be fooled into thinking using bash namerefs is safer than eval. Like for eval, you still need to make sure the content of $Name is a valid shell variable name. Values like x[`evil-command>&2`0] would still cause that evil-command to be executed when you expand $Name or ${#Name}. Same applies to ${!var}.

With ksh93, you could use multi-dimensional arrays instead:

a[0]=(a b c) i=0 echo "${#a[i][@]}" 

zsh has more consistent ways to combine its expansion operators:

a0=(a b c) i=0 name=a$i echo ${(P)#name} 

(P for indirect parameter expansion).

3
  • Almost there. Could you, please, see my edit? Commented Jun 1, 2017 at 19:40
  • I cannot do "typeset", because I need variable Name to contain the string of the original array, i.e. "array0" Commented Jun 1, 2017 at 19:52
  • @Naz, then you can use Name=a$i; typeset -n ref="$Name"; echo "${#ref[@]}" or use eval or the other alternatives. Commented Jun 1, 2017 at 19:57
2

You can use eval explicitly, but don't overuse it:

eval "len=\${#$Name[@]}" 
2
  • Thank you - this works. Let's see if there are other ways to do it Commented May 31, 2017 at 20:39
  • No sure about the consequences of overusing "eval", but it seems to be working very well for finding the number of elements in the referenced array, as well as reading the specific element from array using eval elem=\${$Name[$i]} Commented Jun 1, 2017 at 20:08

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.