6

I am trying to do the following in my script:

#/bin/bash -x
var1=www
var2=www2
var3=www3
var4=www4
for i in 1 2 3 4; do
   echo \$var$i
done

Obviously, this doesn't work as expected and results in the following output:

$var1
$var2
$var3
$var4

How can I dynamically reference the variables in my loop?

11

Are you looking for this?

$ cat indirection.bash
#!/bin/bash -x

var1=www
var2=www2
var3=www3
var4=www4
for i in 1 2 3 4; do
        s="var${i}"
        echo "${!s}"
done

 

$ ./indirection.bash
www
www2
www3
www4
  • How does your script work without ! in shebang!? – sasha.sochka Aug 1 '13 at 20:43
  • @sasha.sochka Copy-paste mistake from the OP's code...fixed, thanks. – Adrian Frühwirth Aug 2 '13 at 7:19
7

You could use an array:

#/bin/bash -x

declare -a vars=(
    www
    www2
    www3
    www4
)

for var in "${vars[@]}"; do
   echo "$var"
done

Or iterate with index:

for i in "${!vars[@]}"; do
    echo "${vars[$i]}"
done
  • 5
    NOte, you always want to quote "${vars[@]}", otherwise the for loop will break on any whitespace in the array element values. e.g. var=("elem 1" "elem 2"). Only omit the double quotes if you want this (usually unexpected) behaviour. – glenn jackman Jul 31 '13 at 10:59
  • You are right, I forgot it. – ahilsend Jul 31 '13 at 12:53
3

Normally shell expands variable only once. You can use indirect expand or ask shell to expand it one more time, for example:

eval "val=\$var$i"; echo "$val";

instead of just:

echo "\$var$i"

This method is very portable, but uses evil eval.

Using indirect expansion as shown in other answers (see Parameter Expansion in man bash) ${!VAR_NAME} is a good solution, when portability is not necessary and you are allowed to use BASH extensions.

2

Use an associative array. There's no good reason to generate variable names like this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.