Thursday, October 22, 2009

More on Loops








 

 










More on Loops



Breaking Out of a Loop



Sometimes you may want to make an immediate exit from a loop. To just exit from the loop (and not from the program), you can use the break command, whose format is simply





break



When the break is executed, control is sent immediately out of the loop, where execution then continues as normal with the command that follows the done.



The Unix command true serves no purpose but to return an exit status of zero. The command false also does nothing but return a nonzero exit status. If you write





while true

do

...

done



the while loop will theoretically be executed forever because true always returns a zero exit status. By the way, the : command also does nothing but return a zero exit status, so an "infinite" loop can also be set up with





while :

do

...

done



Because false always returns a nonzero exit status, the loop





until false

do

...

done



will theoretically execute forever.



The break command is often used to exit from these sorts of infinite loops, usually when some error condition or the end of processing is detected:





while true

do

cmd=$(getcmd)



if [ "$cmd" = quit ]

then

break

else

processcmd "$cmd"

fi

done



Here the while loop will continue to execute the getcmd and processcmd programs until cmd is equal to quit. At that point, the break command will be executed, thus causing the loop to be exited.



If the break command is used in the form





break n



the n innermost loops are immediately exited, so in





for file

do

...

while [ "$count" -lt 10 ]

do

...

if [ -n "$error" ]

then

break 2

fi

...

done

...

done



both the while and the for loops will be exited if error is nonnull.



Skipping the Remaining Commands in a Loop



The continue command is similar to break, only it doesn't cause the loop to be exited, merely the remaining commands in the loop to be skipped. Execution of the loop then continues as normal. Like the break, an optional number can follow the continue, so





continue n



causes the commands in the innermost n loops to be skipped; but execution of the loops then continues as normal.





for file

do

if [ ! -e "$file" ]

then

echo "$file not found!"

continue

fi



#

# Process the file

#



...

done



Each value of file is checked to make sure that the file exists. If it doesn't, a message is printed, and further processing of the file is skipped. Execution of the loop then continues with the next value in the list. Note that the preceding example is equivalent to writing





for file

do

if [ ! -e "$file" ]

then

echo "$file not found!"

else

#

# Process the file

#



...

fi

done



Executing a Loop in the Background



An entire loop can be sent to the background for execution simply by placing an ampersand after the done:





$ for file in memo[1-4]

> do

> run $file

> done & Send it to the background

[1] 9932

$

request id is laser1-85 (standard input)

request id is laser1-87 (standard input)

request id is laser1-88 (standard input)

request id is laser1-92 (standard input)



I/O Redirection on a Loop



You can also perform I/O redirection on the entire loop. Input redirected into the loop applies to all commands in the loop that read their data from standard input. Output redirected from the loop to a file applies to all commands in the loop that write to standard output:





$ for i in 1 2 3 4

> do

> echo $i

> done > loopout Redirect loop's output to loopout

$ cat loopout

1

2

3

4

$



You can override redirection of the entire loop's input or output by explicitly redirecting the input and/or output of commands inside the loop. To force input or output of a command to come from or go to the terminal, use the fact that /dev/tty always refers to your terminal. In the following loop, the echo command's output is explicitly redirected to the terminal to override the global output redirection applied to the loop:





for file

do

echo "Processing file $file" > /dev/tty

...

done > output



echo's output is redirected to the terminal while the rest goes to the file output.



Naturally, you can also redirect the standard error output from a loop, simply by tacking on a 2> file after the done:





while [ "$endofdata" -ne TRUE ]

do

...

done 2> errors



Here output from all commands in the loop writing to standard error will be redirected to the file errors.



Piping Data Into and Out of a Loop



A command's output can be piped into a loop, and the entire output from a loop can be piped into another command in the expected manner. Here's a highly manufactured example of the output from a for command piped into wc:





$ for i in 1 2 3 4

> do

> echo $i

> done | wc �l

4

$



Typing a Loop on One Line



If you find yourself frequently executing loops directly at the terminal, you'll want to use the following shorthand notation to type the entire loop on a single line: Put a semicolon after the last item in the list and one after each command in the loop. Don't put a semicolon after the do.



Following these rules, the loop





for i in 1 2 3 4

do

echo $i

done



becomes





for i in 1 2 3 4; do echo $i; done



And you can type it in directly this way:





$ for i in 1 2 3 4; do echo $i; done

1

2

3

4

$



The same rules apply to while and until loops.



if commands can also be typed on the same line using a similar format:





$ if [ 1 = 1 ]; then echo yes; fi

yes

$ if [ 1 = 2 ]; then echo yes; else echo no; fi

no

$



Note that no semicolons appear after the then and the else.












     

     


    No comments:

    Post a Comment