2

How do I use a for loop to define a variable, and its value, and be able to evaluate it?

I can't figure out the evaluation part, but using the for loop to define the variable and its value seems to work. Specifically,

for i in {1..4}
do
    export my${i}var="./path${i}_tofile"
   # or
   # export my${i}var=./path${i}_tofile
   # or
   # eval "my${i}var=\"./path${i}_tofile\""
    echo $[my${i}var]
done

The echo does not evaluate correctly, but the shell does correctly create the variable and the value.

echo $my1var

returns

./path1_tofile

But I need to evaluate the variables using the $i as part of their names.

jlconne
  • 21
  • 1
  • 3

3 Answers3

2

You should instead use an array variable:

declare -a myvar
for i in {1..4}
do
    myvar[$i]="./path${i}_tofile"
done

More details: http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_10_02.html

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
2

This is how it gets complicated if you don't use an array:

for i in {1..4}
do
    declare my${i}var="./path${i}_tofile"
    tmpvar=my${i}var             # temporary variabled needed for...
    echo "$tmpvar=${!tmpvar}"    # bash indirect variable expansion
done
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • This is great. If you could add an explanation for the last part `"$tmpvar=${!tmpvar}"` would be fabulous for such newbies like me :-) – George Vasiliou Feb 05 '17 at 02:10
  • 1
    Check this answer for a nice explanation: http://stackoverflow.com/a/10820497/7552 – glenn jackman Feb 05 '17 at 02:15
  • Indirect Expansion. Sounds like eval i think. – George Vasiliou Feb 05 '17 at 02:21
  • 1
    No. `eval` will execute potential command substitutions. Indirect expansion will not. Test with this: ``tmpvar='foo`execute nasty command`'; echo "${!tmpvar}"; eval echo "${tmpvar}"`` -- the indirect expansion is essentially "variable not found, substitute the empty string", eval executes the nasty command. – glenn jackman Feb 06 '17 at 14:24
0

Just replace the echo you are using with:

v=my${i}var
echo ${!v}

Then, the script:

#!/bin/bash

for i in {1..4}
do
    export my${i}var="./path${i}_tofile"
    v=my${i}var
    echo ${!v}
done

Will execute as:

$ ./script
./path1_tofile
./path2_tofile
./path3_tofile
./path4_tofile

But, honestly, working with indirect variables is never easy.
Please consider using Indexed arrays (in this use case even normal arrays will work):

declare -A myvar

for i in {1..4}
do
    myvar[i]="./path${i}_tofile"
    echo "${myvar[i]}"
done
  • looks like an array is the way to go - thanks! I will need to reference the new variables later in the same script, so using an array index is the best method to be able to enter another for loop and re-reference the same variables. The indirect expansion explanation works great for the current loop and sets the variable values correctly, but doesn't allow me to reference the variables afterward with the same index ...for I in {1..4} loop – jlconne Feb 06 '17 at 18:16