for loops in bash

I don’t do much shell scripting, but every once in a while I use it to automate things. I was playing around with bash today and thought this might interest others.

Define an array variable
$ servers=(server purple yellow dan);
$ echo $servers
server

Redefine it.
$ servers=(firstserver server purple yellow dan);
$ echo $servers
firstserver

That’s not what I want. So how do we access the values? Let’s try a for loop.
$ for name in $servers; do echo $name; done;
$ echo $servers
firstserver

Well that didn’t do it. Let’s try to access the second value with array notation.
$ for name in $servers; do echo $servers[1]; done;
firstserver[1]

If you look carefully at this you’ll notice that what is happening is that you are concatenating the return value from $server with [1]. Try it again with this line.

$ for name in $servers; do echo $servers[a]; done;
firstserver[a]

And again.
$ for name in $servers; do echo $servers.a; done;
firstserver.a

As long as you use a character that is not a valid part of a variable name, you get concatenation.
e.g. don’t use an alphanumeric.
$ for name in $servers; do echo $serversabc; done;

There is no variable called serverabc, so you get a blank line.

It turns out that bash has weird syntax for working with variables.
$ echo ${servers[2]}
purple

Add another value.
$ servers[5]=finalvalue
$ echo ${servers[5]}
finalvalue

So how about we separate out the loop variable like this?
$ for name in $servers; do echo $servers${name}; done;
firstserverfirstserver

Well, we’re getting warmer.
$ for name in $servers; do echo $name; done;
firstserver

This is getting frustrating. Let’s back up and try just listing a bunch of stuff in a list.
$ for name in firstserver server purple yellow dan finalvalue; do echo $name; done;
firstserver
server
purple
yellow
dan
finalvalue

So we can make a for loop iterate through items, but the normal way of accessing elements of an array doesn’t work in bash. It turns out that you need special syntax.

$ echo ${servers[@]}
firstserver server purple yellow finalvalue finalvalue

And to loop through everything like we wanted to do at the start.
$ for name in ${servers[@]}; do echo $name; done;
firstserver
server
purple
yellow
dan
final value

That wasn’t so hard was it?