Download   Online Shop   Red Hat Network
Home  |  Products & Services  |  Support  |  Training  |  Partners  |  Documentation   
Red Hat Documentation

Overview | HOWTOs | mini-HOWTOs | FAQs | Linux Man-Pages

Loops

3.8. Loops

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

 

 
 
Search for:  on    Powered by Google
Products & Services   :   Download   :   Support   :   Training   :   Partners & Programs
© 2000 Red Hat, Inc. All right reserved.       About Red Hat   :   Legal statement   :   Privacy statement   :   Y2K statement   :   Contact Red Hat