Previous Section  < Day Day Up >  Next Section

10.7. Looping Commands

Looping constructs allow you to execute the same statements a number of times. The C shell supports two types of loops: foreach and while. The foreach loop is used when you need to execute commands on a list of items, one item at a time, such as a list of files or a list of usernames. The while loop is used when you want to keep executing a command until a certain condition is met.

10.7.1 The foreach Loop

The foreach command is followed by a variable and a wordlist enclosed in parentheses. The first time the loop is entered, the first word in the list is assigned to the variable. The list is shifted to the left by one and the body of the loop is entered. Each command in the loop body is executed until the end statement is reached. Control returns to the top of the loop. The next word on the list is assigned to the variable, the commands after the foreach line are executed, the end is reached, control returns to the top of the foreach loop, the next word in the wordlist is processed, and so on. When the wordlist is empty, the loop ends.

FORMAT


foreach variable (wordlist)

     commands

end


Example 10.36.

1   foreach person (bob sam sue fred)

2        mail $person < letter

3   end


EXPLANATION

  1. The foreach command is followed by a variable, person, and a wordlist enclosed in parentheses. The variable person will be assigned the value bob the first time the foreach loop is entered. Once bob has been assigned to person, bob is shifted off (to the left) and sam is at the beginning of the list. When the end statement is reached, control starts at the top of the loop, and sam is assigned to the variable person. This procedure continues until fred is shifted off, at which time the list is empty and the loop is over.

  2. The user bob will be mailed the contents of the file letter the first time through the loop.

  3. When the end statement is reached, loop control is returned to the foreach, and the next element in the list is assigned to the variable person.

Example 10.37.

(The Command Line)

% cat maillist

tom

dick

harry

dan

(The Script)

     #!/bin/csh -f

     # Scriptname: mailtomaillist

1    foreach person (`cat maillist`)

2        mail $person <<EOF

         Hi $person,

         How are you?  I've missed you. Come on over

         to my place.

         Your pal,

                  $LOGNAME@`uname –n`

     EOF

3    end


EXPLANATION

  1. Command substitution is performed within the parentheses. The contents of the file maillist become the wordlist. Each name in the wordlist (tom, dick, harry , dan) is assigned, in turn, to the variable person. After the looping statements are executed and the end is reached, control returns to the foreach, a name is shifted off from the list, and assigned to the variable person. The next name in the list replaces the one that was just shifted off. The list therefore decreases in size by one. This process continues until all the names have been shifted off and the list is empty.

  2. The here document is used. Input is sent to the mail program from the first EOF to the terminating EOF. (It is important that the last EOF is against the left-hand margin and has no surrounding whitespace.) Each person in the list will be sent the mail message.

  3. The end statement for the foreach loop marks the end of the block of lines that is executed within this loop. Control returns to the top of the loop.

Example 10.38.

1   foreach file (*.c)

2        cc $file -o $file:r

    end


EXPLANATION

  1. The wordlist for the foreach command is a list of files in the current directory ending in .c (i.e., all the C source files).

  2. Each file in the list will be compiled. If, for example, the first file to be processed is program.c, the shell will expand the cc command line to

    
    cc program.c -o program
    
    

    The :r causes the .c extension to be removed.

Example 10.39.

(The Command Line)

1    % runit f1 f2 f3 dir2 dir3



(The Script)

     #!/bin/csh -f

     # Scriptname: runit

     # It loops through a list of files passed as arguments.



2    foreach arg  ($*)

3       if ( –e $arg ) then

        ...         Program code continues here



        else

        ...         Program code continues here

        endif

4    end

5    echo "Program continues here"


EXPLANATION

  1. The script name is runit; the command-line arguments are f1, f2, f3, dir2, and dir3.

  2. The $* variable evaluates to a list of all the arguments (positional parameters) passed in at the command line. The foreach command processes, in turn, each of the words in the wordlist, f1, f2, f3, dir2, and dir3. Each time through the loop, the first word in the list is assigned to the variable arg. After a word is assigned, it is shifted off (to the left) and the next word is assigned to arg, until the list is empty.

  3. The commands in this block are executed for each item in the list until the end statement is reached.

  4. The end statement terminates the loop after the wordlist is empty.

  5. After the loop ends, the program continues to run.

10.7.2 The while Loop

The while loop evaluates an expression, and as long as the expression is true (nonzero), the commands below the while command will be executed until the end statement is reached. Control will then return to the while expression, the expression will be evaluated, and if still true, the commands will be executed again, and so on. When the while expression is false, the loop ends and control starts after the end statement.

Example 10.40.

(The Script)

     #!/bin/csh -f

1    set num = 0

2    while ($num < 10)

3         echo $num

4         @ num++        # See arithmetic.

5    end

6    echo "Program continues here"


EXPLANATION

  1. The variable num is set to an initial value of 0.

  2. The while loop is entered and the expression is tested. If the value of num is less than 10, the expression is true, and lines 3 and 4 are executed.

  3. The value of num is displayed each time through the loop.

  4. The value of the variable num is incremented. If this statement were omitted, the loop would continue forever.

  5. The end statement terminates the block of executable statements. When this line is reached, control is returned to the top of the while loop and the expression is evaluated again. This continues until the while expression is false (i.e., when $num is 10).

  6. Program execution continues here after the loop terminates.

Example 10.41.

(The Script)

     #!/bin/csh -f

1    echo –n  "Who wrote \"War and Peace\"?"

2    set answer = $<

3    while ("$answer" != "Tolstoy")

          echo "Wrong, try again\!"

4         set answer = $<

5    end

6    echo Yeah!


EXPLANATION

  1. The user is asked for input.

  2. The variable answer is assigned whatever the user inputs.

  3. The while command evaluates the expression. If the value of $answer is not equal to the string Tolstoy exactly, the message Wrong, try again! is printed and the program waits for user input.

  4. The variable answer is assigned the new input. This line is important. If the value of the variable answer never changes, the loop expression will never become false, thus causing the loop to spin infinitely.

  5. The end statement terminates the block of code inside the while loop.

  6. If the user enters Tolstoy, the loop expression tests false, and control goes to this line. Yeah! is printed.

10.7.3 The repeat Command

The repeat command takes two arguments, a number and a command. The command is executed that number of times.

Example 10.42.

% repeat 3 echo hello

hello

hello

hello


EXPLANATION

The echo command is executed three times.

10.7.4 Looping Control Commands

The shift Command

The shift command, without an array name as its argument, shifts the argv array by one word from the left, thereby decreasing the size of the argv array by one. Once shifted off, the array element is lost.

Example 10.43.

(The Script)

     #!/bin/csh -f

     # Scriptname: loop.args

1    while ($#argv)

2         echo $argv

3         shift

4    end



(The Command Line)

5    % loop.args a b c d e

     a b c d e

     b c d e

     c d e

     d e

     e


EXPLANATION

  1. $#argv evaluates to the number of command-line arguments. If there are five command-line arguments, a, b, c, d, and e, the value of $#argv is 5 the first time in the loop. The expression is tested and yields 5, true.

  2. The command-line arguments are printed.

  3. The argv array is shifted one to the left. There are only four arguments left, starting with b.

  4. The end of the loop is reached, and control goes back to the top of the loop. The expression is re-evaluated. This time, $#argv is 4. The arguments are printed, and the array is shifted again. This goes on until all of the arguments are shifted off. At that time, when the expression is evaluated, it will be 0, which is false, and the loop exits.

  5. The arguments a, b, c, d, and e are passed to the script via the argv array.

The break Command

The break command is used to break out of a loop so that control starts after the end statement. It breaks out of the innermost loop. Execution continues after the end statement of the loop.

Example 10.44.

    #!/bin/csh -f

    # Scriptname: baseball

1   echo -n "What baseball hero died in August 1995? "

2   set answer = $<

3   while ("$answer" !~ [Mm]*)

4             echo "Wrong\! Try again."

              set answer = $<




EXPLANATION

  1. The user is asked for input.

  2. The input from the user is assigned to the variable answer (answer: Mickey Mantle).

  3. The while expression reads: While the value of answer does not begin with a big M or little m, followed by zero or more of any character, enter the loop.

  4. The user gets to try again. The variable is reset.

  5. If the variable answer matches M or m, break out of the loop. Go to the end statement and start executing statements at line 7.

  6. The end statement terminates this block of statements after the loop.

  7. After the loop exits, control starts here and this line is executed.

Example 10.45.

    #!/bin/csh -f

    # Scriptname: database

1   while (1)

        echo "Select a menu item"

2       cat << EOF

        1) Append

        2) Delete

        3) Update

        4) Exit

    EOF

3       set choice = $<

4       switch ($choice)

        case 1:

                 echo "Appending"

5                break           # Break out of loop; not a breaksw

        case 2:

                 echo "Deleting"

                 break



        case 3:

                 echo "Updating"

                 break

        case 4:

                 exit 0

        default:

6                echo "Invalid choice. Try again.

        endsw

7   end

8   echo "Program continues here"


EXPLANATION

  1. This is called an infinite loop. The expression always evaluates to 1, which is true.

  2. This is a here document. A menu is printed to the screen.

  3. The user selects a menu item.

  4. The switch command evaluates the variable.

  5. If the user selects a valid choice, between 1 and 4, the command after the appropriate matching case label is executed. The break statement causes the program to break out of the loop and start execution on line 8. Don't confuse this with the breaksw statement, which merely exits the switch at endsw.

  6. The default is selected when none of the cases above it are matched. After the echo message is displayed, control goes to the end of the loop and then starts again at the top of the while. Because the expression after the while always evaluates true, the body of the loop is entered and the menu is displayed again.

  7. End of the while loop statements.

  8. After the loop is exited, this line is executed.

Nested Loops and the repeat Command

Rather than a goto, the repeat command can be used to break out of nested loops. The repeat command will not do this with the continue command.

Example 10.46.

(Simple Script)

    #!/bin/csh -f



(The Output)

Hello, in 1st loop

In 2nd loop

In 3rd loop

Out of all loops


EXPLANATION

  1. Start the first while loop.

  2. Enter the second nested while loop.

  3. Enter the third nested while loop.

  4. The repeat command will cause break to be executed three times; it will break first out of this innermost loop, then the second loop, and last, the first loop. Control continues at line 5.

  5. Program control starts here after loop terminates.

The continue Command

The continue statement starts execution at the top of the innermost loop.

Example 10.47.



4       set done = 1

5   end


EXPLANATION

  1. The variable done is assigned 0.

  2. The expression is tested. It reads: while (! 0). Not 0 is evaluated as true (logical NOT).

  3. If the user entered No, no, or nope (anything starting with N or n), the expression is true and the continue statement returns control to the top of the loop where the expression is re-evaluated.

  4. If answer does not start with N or n, the variable done is reset to one. When the end of the loop is reached, control starts at the top of the loop and the expression is tested. It reads: while (! 1). Not 1 is false. The loop exits.

  5. This marks the end of the while loop.

Example 10.48.

(The Script)

     #!/bin/csh -f

1    if ( ! -e memo ) then

          echo  "memo file non existent"

          exit 1



4        mail -s "Party time"  $person < memo

     end


EXPLANATION

  1. A file check is done. If the file memo does not exist, the user is sent an error message and the program exits with a status of 1.

  2. The loop will assign each person in the list to the variable person, in turn, and then shift off the name in the list to process the next one.

  3. If the person's name is Karl or karl, the continue statement starts execution at the top of the foreach loop (Karl is not sent the memo because his name was shifted off after being assigned to person.) The next name in the list is assigned to person.

  4. Everyone on the mailing list is sent the memo, except karl.

    Previous Section  < Day Day Up >  Next Section