2
a1="one"
a2="two"
a3="three"
for ((i=1;i<=3;i=i+1)); do
     echo $a$i
done 

I have already tried following

  1. echo ${a$i}
  2. echo $((ai))
  3. echo ${a}${i}
  4. c=$(echo a$i)

But none gave the right answer.

4 Answers4

5

That ((i=1;i<=3;i=i+1)) is ksh93 syntax (now also supported by bash and zsh (though you need blanks in between for and (( in zsh)).

In ksh93 and in recent versions of bash (4.3, 2014 or above), you can do:

a1="one"
a2="two"
a3="three"
for ((i=1;i<=3;i=i+1));do
    typeset -n name="a$i"
    printf '%s\n' "$name"
done 

In zsh, you can use variable indirection syntax: ${(e)code} (since May 1996), ${(P)name} (since 1999)

a1="one"
a2="two"
a3="three"
for ((i=1;i<=3;i=i+1));do
    name=a$i
    printf '%s\n' "${(P)name}"
    # or
    code="\$a$i"
    printf '%s\n' "${(e)code}"
    # or combined:
    printf '%s\n' "${(e):-\$a$i}" "${(P)${:-a$i}}"
done 

bash also added its own variable indirection feature, but using a different syntax (in 2.0 in December 1996), and one that means almost the opposite of that of ksh93:

a1="one"
a2="two"
a3="three"
for ((i=1;i<=3;i=i+1));do
    name=a$i
    printf '%s\n' "${!name}"
done 

With any POSIX shell, (including but not limited to ksh93, bash or zsh), you can always do:

a1="one"
a2="two"
a3="three"
i=1; while [ "$i" -le 3 ]; do
    name=a$i
    eval "value=\${$name}"
    printf '%s\n' "$value"
    i=$((i + 1))
done 
3

In bash, if you have a variable containing the name of the variable you want, you can use indirection to access it:

a1="one"
a2="two"
a3="three"
for((i=1;i<=3;i=i+1));do
    name="a$i"
    printf '%s\n' "${!name}"
done 

if you use ${...} to expand a parameter, and the first character is ! then the rest is treated as the name of parameter that itself contains the name of the parameter you want to access.

Eric Renouf
  • 18,431
2

If you are using Bash, the easiest way to accomplish the same thing is to use an array:

a[1]="one"
a[2]="two"
a[3]="three"

for ((i=1; i<=3; i=i+1)); do
    echo "${a[$i]}"
done

You can also loop over the array:

for value in "${a[@]}"; do
     echo "$value"
done
wjandrea
  • 658
0

If one must go down this route, in bash the following works. The idea is to use eval:

#!/bin/bash

a1="one"
a2="two"
a3="three"

for ((i=1;i<=3;i=i+1)); do
  var="a${i}"
  eval out=\$${var}
  echo $out
done

Output:

one
two
three

The eval approach allows for obtaining the value of a referenced variable. So once we have the variable name itself (above, in var as "a${i}" which will be a1, a2, etc), then it is possible to obtain the value of the variable through the eval built-in.

There is some discussion here: What is the "eval" command in bash?

KevinO
  • 845