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.

1
  • 1
    my${i}var="./path${i}_tofile" is not valid. Can you start a new shell and check again? Commented Feb 5, 2017 at 1:27

3 Answers 3

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

Sign up to request clarification or add additional context in comments.

Comments

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

4 Comments

This is great. If you could add an explanation for the last part "$tmpvar=${!tmpvar}" would be fabulous for such newbies like me :-)
Check this answer for a nice explanation: stackoverflow.com/a/10820497/7552
Indirect Expansion. Sounds like eval i think.
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.
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

1 Comment

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.