I’m not sure if this particular post will come in handy to a lot of people, but my bash scripting is still pretty weak and I think the best way to commit this to memory will be to write a short post on it.
I find myself doing one line “for” statements from the command line all the time to make quick loops. Maybe I need to loop through a list of servers and delete them all, maybe I need to ping a group of servers and see if they all reply, maybe I need to build a lot of servers of different flavors at once, etc.
Whatever the reason, I have occasionally come across the need for multiple variables in my loop. For example, let’s say that I have a list of data like this:
1 2 3 4 5 6 7 8 |
| 11111 | Orange | ACTIVE | 50.57.169.1 | 10.183.199.1 | | 11112 | Apple | ACTIVE | 50.57.169.2 | 10.183.199.2 | | 11113 | Banana | ACTIVE | 50.57.158.3 | 10.183.199.3 | | 11114 | Cherry | ACTIVE | 50.57.159.4 | 10.183.194.4 | | 11115 | Pineapple | ACTIVE | 50.57.159.5 | 10.183.192.5 | | 11116 | Melon | ACTIVE | 50.57.149.6 | 10.183.194.6 | | 11117 | Peach | ACTIVE | 50.57.162.7 | 10.183.195.7 | | 11118 | Coconut | ACTIVE | 50.57.162.8 | 10.183.195.8 | |
That format may look familiar if you use the Python Command Line tool for Rackspace Cloud Servers (http://pypi.python.org/pypi/python-cloudservers/1.2)
Now let’s say that I want to create an image of the 8 servers listed above. I would usually put the above table in a tmp file, and just call out the Server ID. Something like:
1 |
$ for x in `awk '{print $2}' /tmp/servers`; do myservers image-create $x Image-of-$x; done |
This gets the job done, but it is pretty ugly. I end up with image names like “Image-of-11114”, which can be more difficult to read than “Image-of-Cherry”
Using something like the following, I can allow multiple variables in my for loop:
1 |
$ cat /tmp/servers | while read x; do var1=`echo $x | awk '{print $2}'`; var2=`echo $x | awk '{print $4}'`; myservers image-create $var1 Image-of-$var2; done |
The whole idea is to read the full line into a variable (x) and then loops through the line assigning a specific variable to whichever fields I need.
while loops have built-in support for assigning multiple, whitespace separated variables, try something like this:
while read x id x name x; do echo "myservers image-create $id Image-of-$name"; done < temp
I am using x as a placeholder for the | characters in the table, and the last x nabs up the rest of the line after the name, end result is that you get the variables $ip and $name, and it looks cleaner to boot!