2

What I'm trying to do is loop over environment variables. I have a number of installs that change and each install has 3 IPs to push files to and run scripts on, and I want to automate this as much as possible (so that I only have to modify a file that I'll source with the environment variables). The following is a simplified version that once I figure out I can solve my problem.

So given in my.props:

COUNT=2
A_0=foo
B_0=bar
A_1=fizz
B_1=buzz

I want to fill in the for loop in the following script

#!/bin/bash
. <path>/my.props

for ((i=0; i < COUNT; i++))
do
  <script here>
done

So that I can get the values from the environment variables. Like the following(but that actually work):

echo $A_$i $B_$i

or

A=A_$i
B=B_$i
echo $A $B

returns foo bar then fizz buzz

4 Answers4

2
$ num=0
$ declare A_$num=42  # create A_0 and set it to 42
$ echo $A_0
42
$ b=A_$num           # create a variable with the contents "A_0"
$ echo ${!b}         # indirection
42

You can iterate num and use declare to create the variables and indirection to reference them. But wouldn't you really prefer to use arrays?

for i in foo bar baz
do
    some_array+=($i)    # concatenate values onto the array
done

or

string="foo bar baz"
some_array=($string)

How about this?

$ cat IPs
192.168.0.1
192.168.0.2
192.168.0.3
$ cat readips
#!/bin/bash
while read -r ip
do
    IP[count++]=ip                 # is it necessary to save them in an array,
    do_something_directly_with ip  # if you use them right away?
done < IPs
Dennis Williamson
  • 62,149
  • 16
  • 116
  • 151
1
A=`eval echo \$A_$i`
Mo.
  • 2,236
  • 17
  • 9
1

Found the answer at Indirect References Chapter of Advanced Bash Scripting Guide

I needed to do

eval A=\$A_$i
eval B=\$B_$i
  • 1
    I recommend that you use declare to do it instead of eval. Even though you may not run into it in this instance, there are security implications to using eval that can be avoided if declare can be used to accomplish the same thing. – Dennis Williamson Apr 19 '10 at 18:13
0

Not sure I entirely follow your question, but if you want the variables availbe to children scripts use the export built-in:

kbrandt@kbrandt:~/scrap$ help export
export: export [-nf] [name[=value] ...] or export -p
    NAMEs are marked for automatic export to the environment of
    subsequently executed commands.

From what I think you might trying to do, I would just put the IPs in one file, one IP per line. Then have the install script read the ip as a command line argument:

while read ip; do
   ./install-script "$ip"
done < file_with_ips

If there is more than one piece of data per record, than you can deliminate them:

kbrandt@kbrandt:~/scrap$ cat file_with_data 
192.168.2.5:foobar:baz
kbrandt@kbrandt:~/scrap$ while IFS=":" read -r ip data1 data2; do 
> echo "$ip@$data1@$data2"
> done < file_with_data
192.168.2.5@foobar@baz
Kyle Brandt
  • 83,619
  • 74
  • 305
  • 448