The while loop allows you to repeatedly execute a group of statements while a command executes successfully. The syntax for the while loop is:
while control_command do statement1 ... statementN done
where,
control_command can be any command that exits with a success or failure status.
The statements in the body of the while loop can be any utility commands, user programs, shell scripts, or shell statements.
When a while statement is executed, the control_command is evaluated. If the control_command succeeds, all the statements between the do and done are executed, and then the controlling command is again executed.
As long as the control_command succeeds, the loop body continues to execute. As soon as the control_command fails, the statement following the done statement is executed.
The do statement is a separate statement and must appear on a line by itself (not on the line containing the while command_control statement) unless it is preceded by a semicolon. The same is true of the done statement. It must exist on a line of its own or be preceded by a semicolon if it exists at the end of the last statement line in the loop.
The while Loop Syntax
The following examples are all valid forms of the while syntax. While the contents of $var are equal to the string string_value, the loop continues.
while [ "$var" = "string_value" ] while [[ "$var" == "string_value" ]]
In the following example, while the value of $num is less than or equal to 10, the loop continues.
while [ $num -le 10 ] while (( num <= 10 ))
Just as in the if statement, the controlling command of a while loop is often a ((…)) or [[ … ]] or [ … ] command. Frequently, a variable within the test changes value in the while loop so that the loop eventually terminates.
The following two examples show how you can alter numeric values in the loop body to cause the while loop to terminate.
$ cat whiletest.sh #!/bin/sh # Script name: whiletest.sh num=5 while [ $num -le 10 ] do echo $num num=‘expr $num + 1‘ done
$ cat whiletest.ksh #!/bin/ksh # Script name: whiletest.ksh num=5 while (( num <= 10 )) do echo $num (( num = num + 1 )) # let num=num+1 done
There are two commands in the shell that always return the same exit status. These commands are true and false. The true command always causes the test to succeed (with zero errors), and the false command always causes the test to fail (with some number of errors). The following example causes an infinite loop.
while true
To debug your script by forcing the condition to be false, use the following:
while false
Using the ((…)) syntax of the Korn shell, which evaluates numeric expressions, makes it possible for a single numeric variable or value to be present in the while test. In this case, if the value of the numeric expression is nonzero, the test succeeds, and the loop executes. If the value of the numeric expression is 0, the test fails, and the code following the loop executes.
$ cat whiletest2.ksh #!/bin/ksh # Script name: whiletest2.ksh num=5 while (( num )) do echo $num let num=num-1 # let "num = num - 1" done
The statement: while (( num )) evaluates to the logical negation of num. Therefore, the program remains in the loop as long as the value of num is not 0.
Example of Using a while Loop
In the following example, the variable num is initialized to 1, and a while loop is entered. This while loop uses num instead of $num because the ((…)) command automatically does variable expansion. Using num forces integer arithmetic, whereas using $num performs arithmetic on strings. Integer arithmetic is faster.
Within the while loop, the current value of num is printed to stdout. The variable num is incremented and the condition in the while statement is checked again. If the value of the variable num did not change within the while loop, the program would be in an infinite loop (that is, a loop that never ends).
$ cat while.ksh #!/bin/ksh # Script name: while.ksh num=1 while (( num < 6 )) do print "The value of num is: $num" (( num = num + 1 )) # let num=num+1 done print "Done."
$ ./while.ksh Value of num is: 1 Value of num is: 2 Value of num is: 3 Value of num is: 4 Value of num is: 5 Done.
Keyboard Input
You can place the read statement in the while condition. Each time a user inputs something from a keyboard, a loop executes. When a user presses ControlD, this tells the read statement that input is complete, the condition becomes false, and execution jumps to after the done statement.
$ cat readinput.ksh #!/bin/ksh # Script name: readinput.ksh print -n "Enter a string: " while read var do print "Keyboard input is: $var" print -n "\nEnter a string: " done print "End of input."
$ ./readinput.ksh Enter a string: OK Keyboard input is: OK Enter a string: This is fun Keyboard input is: This is fun Enter a string: I’m finished. Keyboard input is: I’m finished. Enter a string: ^d End of input.
Redirecting Input for a while Loop
Instead of input coming from the keyboard or stdin, you can specify a file from which to read the input. Consider the following example:
$ cat internalredir.ksh #!/bin/ksh # Script name: internalredir.ksh # set the Internal Field Separator to a colon IFS=: while read name number do print "The phone number for $name is $number" done < phonelist
In the example above, the redirection is performed at the end of the while block:
done < phonelist
By redirecting on stdin, the file is opened only once. Each time around the loop, read returns the next line from the file. Lines are read into the loop while there are lines to read in from the file. After the end of the file is reached, a true state no longer exists, and the loop terminates. After the loop terminates, the statement that follows the done statement executes.
$ cat phonelist Claude Rains:214-555-5107 Agnes Moorehead:710-555-6538 Rosalind Russel:710-555-0482 Loretta Young:409-555-9327 James Mason:212-555-2189
$ ./internalredir.ksh The phone number for Claude Rains is 214-555-5107 The phone number for Agnes Moorehead is 710-555-6538 The phone number for Rosalind Russel is 710-555-0482 The phone number for Loretta Young is 409-555-9327 The phone number for James Mason is 212-555-2189