Previous | Table of Contents | Next |
In this chapter, youll learn how to set up and use loops in your shell scripts. Loops enable you to execute a series of commands multiple times. Two main types of loops are
The while loop enables you to execute a set of commands repeatedly until some condition occurs. It is usually used when you need to manipulate the value of a variable repeatedly.
The for loop enables you to execute a set of commands repeatedly for each item in a list. One of its most common uses is in performing the same set of commands for a large number of files.
In addition to these two types of loops, ksh and bash support an additional type of loop called the select loop. It frequently presents a menu of choices to a shell scripts user.
The first section of this chapter explains the while loop and its uses. The second section of this chapter shows you how to use the for and select loops.
The basic syntax of the while loop is
while command do list done
Here command is a single command to execute, whereas list is a set of one or more commands to execute. Although command can be any valid UNIX command, it is usually a test expression of the type covered in the last chapter.
list is commonly referred to as the body of the while loop because it contains the heart or guts of the loop. The do and done keywords are not considered part of the body of the loop because the shell uses them only for determining where the while loop begins and ends.
The execution of a while loop proceeds according to the following steps:
If both command and list are short, the while loop is written in a single line as follows:
while command ; do list ; done
Here is a simple example that uses the while loop to display the numbers zero to nine:
x=0 while [ $x -lt 10 ] do echo $x x=`echo "$x + 1" | bc` done
Its output looks like this:
0 1 2 3 4 5 6 7 8 9
Each time this loop executes, the variable x is checked to see whether it has a value that is less than 10. If the value of x is less than 10, this test expression has an exit status of 0. In this case, the current value of x is displayed and then x is incremented by 1.
This example uses the bc command to increment x each time the loop executes. If you are not familiar with the bc command, it is covered in detail in Chapter 18, Miscellaneous Tools.
If x is equal to 10 or greater than 10, the test expression returns 1, causing the while loop to exit.
Nesting while Loops
It is possible to use a while loop as part of the body of another while loop as follows:
while command1 ; # this is loop1, the outer loop do list1 while command2 ; # this is loop2, the inner loop do list2 done list3 done
Here command1 and command2 are single commands to execute, whereas list1, list2, and list3 are a set of one or more commands to execute. Both list1 and list3 are optional.
Here you have two while loops, loop1 and loop2. Usually loop1 is referred to as the main loop or outer loop, and loop2 is referred to as the inner loop.
When describing the inner loop, loop2, many programmers say that it is nested one level deep. The term nested refers to the fact that loop2 is located in the body of loop1. If you had a loop3 located in the body of loop2, it would be nested two levels deep. The level of nesting is relative to the outermost loop.
There are no restrictions on how deeply nested loops can be, but you should try to avoid nesting loops more deeply than four or five levels to avoid difficulties in finding and fixing problems in your script.
As an illustration of loop nesting, lets add another countdown loop inside the loop that you used to count to nine:
x=0 while [ "$x" -lt 10 ] ; # this is loop1 do y="$x" while [ "$y" -ge 0 ] ; # this is loop2 do echo "$y \c" y=`echo "$y - 1" | bc` done echo x=`echo "$x + 1" | bc` done
The main change that I have introduced is the variable y. You set it to the value of x-1 before loop2 executes. Because of this, each time loop2 executes you display all the numbers greater than 0 and less than x in reverse order. The output looks like the following:
0 1 0 2 1 0 3 2 1 0 4 3 2 1 0 5 4 3 2 1 0 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
Previous | Table of Contents | Next |