Note: The following material was developed by Claude Cantin of the Research Computing Support Group of the National Research Council of Canada, and is used with his permission.

Control Structures


for var in list

The last example could easily be rewritten as

    #!/bin/sh
    for i in $*
    do
        echo The parameter is $i.
    done
    exit 0

In the above program $* could have been replaced by any list of names. The program would then be changed to:

    #!/bin/sh
    for i in Claude Paul Wayne Roger Tom
    do
        echo The name is $i.
    done
    exit 0

Within the shell, parameters are read as $1 for the first parameter, $2 for the second parameter, $3 for the third parameter, and so on. $* is the entire list of parameters.

If the ``in list" is omitted, the list taken is the list of parameters passed to the shell on the command line.

while condition

The condition involves the test statement seen above, where one value is compared with another. If the comparison is true, the commands within the loop are executed. If not, they are not executed.

Using another form of the above example,

    #!/bin/sh
    while test $# -gt 0; do
        echo parameter $1
        shift
    done
    exit 0

Note that the while and do are on the same line, and that in this case they must be separated by a semicolon. The semicolon is a command separator.


until loop

Again, another way to write the above example is to use the until control sequence:

    #!/bin/sh
    until test $# -eq 0
    do
        echo parameter $1
        shift
    done
    exit 0


if statement

What would happen if no parameters had been passed to the script? Here is how one can verify that there is at least one parameter in the list:

    #!/bin/sh
    if test $# -eq 0
    then
        echo There must be at least one parameter on the command line
    else
        until test $# -eq 0
        do
            echo parameter $1
            shift
        done
    fi
    exit 0
Another way to write this same program is
    #!/bin/sh
    if test $# -eq 0
    then
        echo There must be at least one parameter on the command line
        exit 1
    fi
    until test $# -eq 0
    do
        echo parameter $1
        shift
    done
    exit 0
Note that the format of the if statement is
if comparison
then
. . .
else
. . .
fi
The else is optional, or if followed by another if, else if could be replaced by elif. The statement is ended by fi (``if" spelled backwards).


case: Selections

Often, one wants to perform specific actions on specific values of a variable. This is an example of such a program:

    #!/bin/sh
    case $# in
        0) echo no parameters;;
        1) echo only one parameter.
           echo put commands to be executed here.;;
        *) echo more than one parameter.
           echo enter code here.;;
    esac
    exit 0

Wildcards can be used as items within the case statement. Hence * means ``anything matches".

Note the use of the double semicolons. These are always required to terminate case pattern statements.

A much more powerful case example would be:

while :
do
    echo "Would you like to continue? \c"
    read ANS
    case $ANS in
        [yY] | [yY][eE][sS])  echo "Fine, then we'll continue."
            break
            ;;
        [nN] | [nN][oO]) echo "We shall now stop."
            exit
            ;;
        *) echo "You must enter a yes or no verdict!"
    esac
done
echo "\nWe are now out of the while loop."

The example shows a number of tricks sometimes used during shell programming. The first is the use of an infinite while loop by using the : operator instead of a test operator. The : always returns a successful result (represented by a return code of 0). (In general, the test operator is actually not needed - but is almost always used - to control loops. As test always returns 0 for a successful comparison and 1 for a non-successful comparison, it is easy to use. In reality, any appropriate UNIX command could be used to control the loops. The loop would then be entered if a return code of 0 were returned by the command.)

The second trick is done with the use of the break command. When break is encountered, the execution flow branches to the end of the current loop. In this case, the while loop.

Finally, the content of ANS is compared with a number of pattern matching sequences. Those pattern matching sequences actually replace a large number of if statements. In our case, the statement

[Yy] | [Yy][Ee][Ss] )
would match Y, y, YES, YEs, Yes, yES, yEs, yeS, YeS and yes. The vertical bar | is an OR sign.

In fact, all shell metacharacters are allowed in forming a pattern match string. In the example above:

[a-z]* )
would match any string beginning with a lower case character.