|
A loop is a block of code that iterates
(repeats) a list of commands as long as the loop control condition is
true. - for (in)
This is the basic looping construct. It differs significantly
from its C counterpart. for [arg] in [list] do command... done Note that list may contain wild cards. Note further that if do is on same line as
for, there needs to be a semicolon before list. for [arg] in [list] ; do
Example 3-26. Simple for loops #!/bin/bash
for planet in Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune Pluto
do
echo $planet
done
echo
# Entire 'list' enclosed in quotes creates a single variable.
for planet in "Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune Pluto"
do
echo $planet
done
exit 0 |
Note: Each [list] element
may contain multiple parameters. This is useful when
processing parameters in groups. In such cases, use the
set command (see Example 3-40)
to force parsing of each [list]
element and assignment of each component to the positional
parameters.
Example 3-27. for loop with two parameters in each
[list] element #!/bin/bash
# Planets revisited.
# Want to associate name of each planet with its distance from the sun.
for planet in "Mercury 36" "Venus 67" "Earth 93" "Mars 142" "Jupiter 483"
do
set $planet # Parses variable "planet" and sets positional parameters.
# May need to save original positional parameters, since they get overwritten.
echo "$1 $2,000,000 miles from the sun"
#-------two tabs---concatenate zeroes onto parameter $2
done
exit 0 |
Omitting the in [list] part of a
for loop causes the loop to operate on
$*, the list of arguments given on the command line
to the script. Example 3-28. Missing in [list] in a
for loop #!/bin/bash
# Invoke both with and without arguments,
# and see what happens.
for a
do
echo $a
done
# 'in list' missing, therefore operates on '$*'
# (command-line argument list)
exit 0 |
Example 3-29. Using efax in batch mode #!/bin/bash
if [ $# -ne 2 ]
# Check for proper no. of command line args.
then
echo "Usage: `basename $0` phone# text-file"
exit 1
fi
if [ ! -f $2 ]
then
echo "File $2 is not a text file"
exit 2
fi
# Create fax formatted files from text files.
fax make $2
for file in $(ls $2.0*)
# Concatenate the converted files.
# Uses wild card in variable list.
do
fil="$fil $file"
done
# Do the work.
efax -d /dev/ttyS3 -o1 -t "T$1" $fil
exit 0 |
- while
This construct tests for a condition at the top of a loop, and keeps
looping as long as that condition is true. while [condition] do command... done As is the case with for/in loops, placing the
do on the same line as the condition test
requires a semicolon. while [condition] ; do Note that certain specialized while loops, as,
for example, a getopts construct, deviate
somewhat from the standard template given here (see Section 3.9). Example 3-30. Simple while loop #!/bin/bash
var0=0
while [ "$var0" -lt 10 ]
do
echo -n "$var0 "
# -n suppresses newline.
var0=`expr $var0 + 1`
# var0=$(($var0+1)) also works.
done
echo
exit 0 |
Example 3-31. Another while loop #!/bin/bash
echo
while [ "$var1" != end ]
do
echo "Input variable #1 (end to exit) "
read var1
# It's not 'read $var1' because value of var1 is being set.
echo "variable #1 = $var1"
# Need quotes because of #
echo
done
# Note: Echoes 'end' because termination condition tested for at top of loop.
exit 0 |
Note: A while loop may have multiple
conditions. Only the final condition determines when the loop
terminates. This necessitates a slightly different loop syntax,
however.
Example 3-32. while loop with multiple conditions #!/bin/bash
var1=unset
previous=$var1
while echo "previous-variable = $previous"
echo
previous=$var1
[ "$var1" != end ] # Keeps track of what "var1" was previously.
# Four conditions on "while", but only last one controls loop.
# Controlling condition has [ test ] brackets.
do
echo "Input variable #1 (end to exit) "
read var1
echo "variable #1 = $var1"
done
# Try to figure out how this all works.
# It's a wee bit tricky.
exit 0 |
Note: A while loop may have its
stdin redirected to a file by a
< at its end (see Example 3-73).
- until
This construct tests for a condition at the top of a loop, and keeps
looping as long as that condition is false (opposite of
while loop). until [condition-is-true] do command... done Note that an until loop tests for the
terminating condition at the top of the loop, differing from a
similar construct in some programming languages. As is the case with for/in loops, placing the
do on the same line as the condition test
requires a semicolon. until [condition-is-true] ; do Example 3-33. until loop #!/bin/bash
until [ "$var1" = end ]
# Tests condition at top of loop.
do
echo "Input variable #1 "
echo "(end to exit)"
read var1
echo "variable #1 = $var1"
done
exit 0 |
- break, continue
The break and continue
loop control commands correspond exactly to their counterparts in
other programming languages. The break command
terminates the loop (breaks out of it), while continue
causes a jump to the next iteration of the loop, skipping all the
remaining commands in that particular loop cycle. Example 3-34. Effects of break and
continue in a loop #!/bin/bash
echo
echo Printing Numbers 1 through 20.
a=0
while [ $a -le 19 ]
do
a=$(($a+1))
if [ $a -eq 3 ] || [ $a -eq 11 ]
# Excludes 3 and 11
then
continue
# Skip rest of this particular loop iteration.
fi
echo -n "$a "
done
# Exercise for reader:
# Why does loop print up to 20?
echo
echo
echo Printing Numbers 1 through 20, but something happens after 2.
##################################################################
# Same loop, but substituting 'break' for 'continue'.
a=0
while [ $a -le 19 ]
do
a=$(($a+1))
if [ $a -gt 2 ]
then
break
# Skip entire rest of loop.
fi
echo -n "$a "
done
echo
echo
exit 0 |
- case (in) / esac
The case construct is the shell equivalent
of switch in C/C++.
It permits branching to one of a number of code blocks, depending
on condition tests. It serves as a kind of shorthand for multiple
if/then/else statements and is an appropriate tool
for creating menus. case "$variable" in
"$condition1" ) command... ;;
"$condition2" ) command... ;;
esac Note: Quoting the variables is recommended. Each test line ends with a left paren ). Each condition block ends with a double
semicolon ;;. The entire case block terminates with an
esac (case spelled
backwards).
Example 3-35. Using case #!/bin/bash
echo
echo "Hit a key, then hit return."
read Keypress
case "$Keypress" in
[a-z] ) echo "Lowercase letter";;
[A-Z] ) echo "Uppercase letter";;
[0-9] ) echo "Digit";;
* ) echo "Punctuation, whitespace, or other";;
esac
# Allows ranges of characters in [square brackets].
exit 0 |
Example 3-36. Creating menus using case #!/bin/bash
# Crude rolodex-type database
clear
# Clear the screen.
echo " Contact List"
echo " ------- ----"
echo "Choose one of the following persons:"
echo
echo "[E]vans, Roland"
echo "[J]ones, Mildred"
echo "[S]mith, Julie"
echo "[Z]ane, Morris"
echo
read person
case "$person" in
# Note variable is quoted.
"E" | "e" )
# Accept upper or lowercase input.
echo
echo "Roland Evans"
echo "4321 Floppy Dr."
echo "Hardscrabble, CO 80753"
echo "(303) 734-9874"
echo "(303) 734-9892 fax"
echo "revans@zzy.net"
echo "Business partner & old friend"
;;
# Note double semicolon to terminate
# each option.
"J" | "j" )
echo
echo "Mildred Jones"
echo "249 E. 7th St., Apt. 19"
echo "New York, NY 10009"
echo "(212) 533-2814"
echo "(212) 533-9972 fax"
echo "milliej@loisaida.com"
echo "Girlfriend"
echo "Birthday: Feb. 11"
;;
# Add info for Smith & Zane later.
* )
# Default option.
echo
echo "Not yet in database."
;;
esac
echo
exit 0 |
- select
The select construct, adopted from the Korn
Shell, is yet another tool for building menus. select variable [in list] do command... break done This prompts the user to enter one of the choices presented in the
variable list. Note that select uses the
PS3 prompt (#? ) by default,
but that this may be changed. Example 3-37. Creating menus using select #!/bin/bash
PS3='Choose your favorite vegetable: '
# Sets the prompt string.
echo
select vegetable in "beans" "carrots" "potatoes" "onions" "rutabagas"
do
echo
echo "Your favorite veggie is $vegetable."
echo "Yuck!"
echo
break
# if no 'break' here, keeps looping forever.
done
exit 0 |
If in list is
omitted, then select uses the list of command
line arguments ($@) passed to the script or to
the function in which the select construct is
embedded. (Compare this to the behavior of a
for variable [in list]
construct with the
in list
omitted.)Example 3-38. Creating menus using select in a function #!/bin/bash
PS3='Choose your favorite vegetable: '
echo
choice_of()
{
select vegetable
# [in list] omitted, so 'select' uses arguments passed to function.
do
echo
echo "Your favorite veggie is $vegetable."
echo "Yuck!"
echo
break
done
}
choice_of beans rice carrots radishes tomatoes spinach
# $1 $2 $3 $4 $5 $6
# passed to choice_of() function
exit 0 |
|