while
The while loop repeats a block of command as long as a condition is true
Format:
while [ conditional expression ]
do
commands
done
You can use [[ ]] or (( )) in place of [ ]
The shell runs the loop in this order:
Evaluate the conditional expression
If it evaluates to false, skip the command block and go to the command that is after done (the loop is finished)
If it evaluates to true, then run the commands once
Loop back and evaluate the conditional expression again
Note that the condition is evaluated in the first step, so it is possible that the loop does not run at all if the condition is false at the beginning
It is recommended that you keep the indentation as shown
Example
num=10
while [[ $num –ge 0 ]] # while num >= 0
do
echo $num # print num
(( num-- )) # then decrement num
done
echo ‘Blast off!’ # After printing the countdown
# sequence, print Blast off!
The until loop repeats a block of command until a condition is true
Format: until [ conditional expression ]
do
commands
done
You can use [[ ]] or (( )) in place of [ ]
The shell runs the loop in this order:
Evaluate the conditional expression
If it evaluates to true, skip the command block and go to the command that is after done (the loop is finished)
If it evaluates to false, then run the commands once
Loop back and evaluate the conditional expression again
Note that the condition is evaluated in the first step, so it is possible that the loop does not run at all if the condition is true at the beginning
It is recommended that you keep the indentation as shown
Example
until (( num == 0 )) # until num is 0
do
read –p “number to square (0 to stop) : ” num # prompt for num
(( num = num * num)) # square num
echo $num # print square
done
The for in loop iterates over an argument list. For every element in the list, it runs the loop one time
Format:
for element in list
do
commands
done
With every pass of the loop, each element in the list is stored in the variable element. The commands usually access element to do some work with it
It is recommended that you keep the indentation as shown
Examples
for file in ~ # for each file in the home directory
do
ls –F $file # list each file
done
for num in 1 3 5 7 9
do
echo $num # will print 1,3,5,7,9 on separate lines
done
All loop statements can be nested. Within each loop there can be another loop
Selection and loop statements can also be nested together. Within a selection block of commands there can be a loop. Likewise, within a block of commands for a loop, there can be selection statements
For example, what does the following code do?
count=0
for file in *
do
if [ -f $file ]
then
(( count ++ ))
fi
done
echo $count regular files
The break statement stops any of the 3 loops
When execution reaches break, it jumps to the command after the loop and the loop is finished
break is typically part of an if construct because you want to stop the loop only when a certain condition is true
Using break can create hard to maintain code because the loop control is being ignored when execution breaks out of the loop
For example:
for num in 1 2 3 4 5 6 7 8 # looks like the loop runs 8 times
do
echo $num
if [ $num –eq 5 ]
then
break # but, surprise, it actually runs 5 times
fi
done
For this reason, you should think twice about using break to stop a loop. If there is a condition that should cause a break in the loop, then that condition should be part of the loop control condition.
In the example above, for num in 1 2 3 4 5 would be much better coding practice
The continue statement causes execution to skip the current iteration of the loop and go on to the next iteration
When execution reaches continue, it jumps to the top of the loop and starts the next iteration of the loop
continue is typically part of an if construct because you want to skip an iteration only when a certain condition is true
Using continue can create hard to maintain code because the loop control is being ignored when execution skips an iteration
For example,
for num in 1 2 3 4 5 6 7 8 # even though the loop goes from 1 to 8
do
if [ $num –eq 5 ]
then
continue # 5 will not get printed
fi
echo $num
done
For this reason, continue should be used only when checking for an error condition and the loop should not run for the iteration that has the error
The shell provides a –x option to help you debug your script
When the –x option is turned on, the shell prints the command in the script before it runs that command
This can help you see all the iterations of a loop and all the decision making with an if construct
To turn the –x option on, put set –x in your script where you want the shell to start printing the command
To turn the –x option off, put set +x in your script where you want the shell to stop printing the command
By using –x and +x options, you can isolate the part of the script that you want to debug
When debug mode is set and the shell prints the command, it adds a + symbol in front of the command, to make it easier for you to differentiate between a command that’s being printed and the script output that’s being printed.
If you want to change the + symbol to something else, change the environment variable PS4. Make sure you also export it so the bash child process that’s interpreting your script can inherit the changed PS4 value
In addition to the –x option, there are some common debugging techniques that programmers should always use
Write one logical block of code at a time, then test and debug it until it works before adding more code. Writing an entire script without incremental debugging is just asking for a headache!
Don’t underestimate the power of the echo utility to print out variable values. Printing intermediate values is one of the classic and most often used debugging techniques
If you use vi as your text editor, here are some basic tips to make coding and debugging easier.
The command: nG
means vi will go to line n. This is useful when the error is on line n and you want to get there fast
The repeat command: . (a single period)
is to repeat the previous command that changes text. This is useful when you need to make the same change in several places in your code
The substitute command works just like the sed s command and will accept regular expressions as well as \t and \n escape characters
The command :set number
means vi will show line numbers along with your code. This is very useful when the error message refers to a certain line number
The command :set ts=2
means that when you hit the tab key, it will indent by 2 spaces.
Indenting is important in making code readable, and most programmers prefer to use the tab key rather than hitting the space bar several times to get the same effect.
The default value for tab in vi is 5 spaces and I find that 5 is too much indentation, especially when there are nested blocks of code. Therefore you can adjust the tab spacing something smaller than 5.
The 2 set commands only last for the current vi session, so when you log out, the setting is gone.
To make the setting last across sessions, create a hidden file called .exrc in your home directory. In that file, enter the 2 set commands without the preceding : and with one command per line. When you run vi the next time, the setting will take effect.