Previous Section  < Day Day Up >  Next Section

8.7. Functions

Functions were introduced to the Bourne shell in AT&T's UNIX System VR2. A function is a name for a command or group of commands. Functions are used to modularize your program and make it more efficient. You may even store functions in another file and load them into your script when you are ready to use them.

Here is a review of some of the important rules about using functions.

  1. The Bourne shell determines whether you are using a built-in command, a function, or an executable program found on the disk. It looks for built-in commands first, then functions, and last, executables.

  2. A function must be defined before it is used.

  3. The function runs in the current environment; it shares variables with the script that invoked it, and lets you pass arguments by assigning them as positional parameters. If you use the exit command in a function, you exit the entire script. If, however, either the input or output of the function is redirected or the function is enclosed within backquotes (command substitution), a subshell is created and the function and its variables and present working directory are known only within the subshell. When the function exits, any variables set there will be lost, and if you have changed directories, you will revert to the directory you were in before invoking the function. If you exit the function, you return to where the script left off when the function was invoked.

  4. The return statement returns the exit status of the last command executed within the function or the value of the argument given, and cannot exceed a value of 255.

  5. Functions exist only in the shell where they are defined; they cannot be exported to subshells. The dot command can be used to execute functions stored in files.

  6. To list functions and definitions, use the set command.

  7. Traps, like variables, are global within functions. They are shared by both the script and the functions invoked in the script. If a trap is defined in a function, it is also shared by the script. This could have unwanted side effects.

  8. If functions are stored in another file, they can be loaded into the current script with the dot command.

FORMAT


function_name () { commands ; commands; }


Example 8.47.

dir () { echo "Directories: " ; ls -l | nawk '/^d/ {print $NF}' ; }


EXPLANATION

The name of the function is dir. The empty parentheses are necessary syntax for naming the function but have no other purpose. The commands within the curly braces will be executed when dir is typed. The purpose of the function is to list only the subdirectories below the present working directory. The spaces surrounding the curly braces are required.

8.7.1 Unsetting Functions

To remove a function from memory, the unset command is used.

FORMAT


unset function_name


8.7.2 Function Arguments and the Return Value

Because the function is executed within the current shell, the variables will be known to both the function and the shell. Any changes made to your environment in the function will also be made to the shell. Arguments can be passed to functions by using positional parameters. The positional parameters are private to the function; that is, arguments to the function will not affect any positional parameters used outside the function.

The return command can be used to exit the function and return control to the program at the place where the function was invoked. (Remember, if you use exit anywhere in your script, including within a function, the script terminates.) The return value of a function is really just the value of the exit status of the last command in the script, unless you give a specific argument to the return command. If a value is assigned to the return command, that value is stored in the ? variable and can hold an integer value between 0 and 255. Because the return command is limited to returning only an integer between 0 and 255, you can use command substitution to capture the output of a function. Place the entire function in backquotes and assign the output to a variable just as you would if getting the output of a UNIX command.

Example 8.48.

(Using the return command)

(The Script)

     #!/bin/sh

     # Scriptname: do_increment

1     increment ()  {

2         sum=`expr $1 + 1`

3         return $sum     # Return the value of sum to the script.

     }

4    echo  –n "The sum is "

5    increment 5    # Call function increment; pass 5 as a parameter.

                    # 5 becomes $1 for the increment function.

6    echo $?        # The return value is stored in $?

7    echo  $sum     # The variable "sum" is known to the function,

                    # and is also known to the main script.



(The Output)

4,6    The sum is 6

7      6


EXPLANATION

  1. The function called increment is defined.

  2. When the function is called, the value of the first argument, $1, will be incremented by 1 and the result assigned to sum.

  3. The built-in return command, when given an argument, returns to the main script after the line where the function was invoked. It stores its argument in the ? variable.

  4. The string is echoed to the screen.

  5. The increment function is called with an argument of 5.

  6. When the function returns, its exit status is stored in the ? variable. The exit status is the exit value of the last command executed in the function unless an explicit argument is used in the return statement. The argument for return must be an integer between 0 and 255.

  7. Although sum was defined in the function increment, it is global in scope, and therefore also known within the script that invoked the function. Its value is printed.

Example 8.49.

(Using command substitution)

(The Script)

     #!/bin/sh

     # Scriptname: do_square

1    function square {

        sq=`expr $1 \* $1`

        echo  "Number to be squared is $1."

2       echo  "The result is $sq "

     }

3    echo "Give me a number to square. "

     read number

4    value_returned=`square $number`    # Command substitution

5    echo   $value_returned



(The Output)

3    Give me a number to square.

     10

5    Number to be squared is 10. The result is 100


EXPLANATION

  1. The function called square is defined. Its function, when called, is to multiply its argument, $1, by itself.

  2. The result of squaring the number is printed.

  3. The user is asked for input. This is the line where the program starts executing.

  4. The function square is called with a number (input from the user) as its argument. Command substitution is performed because the function is enclosed in backquotes. The output of the function, both of its echo statements, is assigned to the variable value_returned.

  5. The command substitution removes the newline between the strings Number to be squared is 10. and The result is 100.

8.7.3 Functions and the dot Command

Storing Functions

Functions are often defined in the .profile file, so that when you log in, they will be defined. Functions cannot be exported, but they can be stored in a file. Then, when you need the function, the dot command is used with the name of the file to activate the definitions of the functions within it.

Example 8.50.

1   $ cat myfunctions

2   go() {   # This file contains two functions

        cd $HOME/bin/prog

      PS1='`pwd` > '

        ls

    }

3   greetings() { echo "Hi $1! Welcome to my world." ; }

4   $ . myfunctions

5   $ greetings george

    Hi george! Welcome to my world.


EXPLANATION

  1. The file myfunctions is displayed. It contains two function definitions.

  2. The first function defined is called go. It sets the primary prompt to the present working directory.

  3. The second function defined is called greetings. It will greet the name of the user passed in as an argument.

  4. The dot command loads the contents of the file myfunctions into the shell's memory. Now both functions are defined for this shell.

  5. The greetings function is invoked and executed.

Example 8.51.

(The .dbfunctions file shown below contains functions to be used by the main program.)

1   $ cat .dbfunctions

2   addon () {    # Function is named and defined in file .dbfunctions

3       while true

        do

            echo "Adding information "

            echo "Type the full name of employee "

            read name

            echo "Type address for employee "

            read address

            echo "Type start date for employee (4/10/88 ) :"

            read startdate

            echo $name:$address:$startdate

            echo –n "Is this correct? "

            read ans

            case "$ans"  in

            [Yy]*)

                    echo "Adding info..."

                    echo $name:$address:$startdate>>datafile

               sort –u datafile –o datafile

               echo –n "Do you want to go back to the main menu? "

               read ans

               if [ $ans = Y –o $ans = y ]

               then

4                  return        # Return to calling program

                else

5                  continue      # Go to the top of the loop

                fi

                ;;

             *)

                echo "Do you want to try again? "

                read answer

             case "$answer" in

             [Yy]*) continue;;

             *) exit;;

             esac

                ;;

        esac

    done

6   }   # End of function definition

-------------------------------------------------------------

(The Script)

7    #!/bin/sh

     # Scriptname: mainprog

     # This is the main script that will call the function, addon



     datafile=$HOME/bourne/datafile

8   . .dbfunctions      # The dot command reads the dbfunctions file into memory

     if [ ! –f $datafile ]

     then

         echo "`basename $datafile` does not exist" 1>&2

         exit 1

     fi

9    echo "Select one: "

     cat <<EOF

         [1] Add info

         [2] Delete info

         [3] Exit

     EOF

     read choice

     case "$choice" in

10        1)    addon          # Calling the addon function

                 ;;

          2)    delete         # Calling the delete function

                 ;;

          3)    update

                 ;;

          4)

                echo Bye

                exit 0

                 ;;

          *)    echo Bad choice

                exit 2

                 ;;

      esac

      echo Returned from function call

      echo The name is $name

      # Variables set in the function are known in this shell.


EXPLANATION

  1. The .dbfunctions file is displayed. It is not a script. It contains only functions.

  2. The addon function is defined. Its function is to add new information to the file datafile.

  3. A while loop is entered. It will loop forever unless a loop control statement such as break or continue is included in the body of the loop.

  4. The return command sends control back to the calling program where the function was called.

  5. Control is returned to the top of the while loop.

  6. The closing curly brace ends the function definition.

  7. This is the main script. The function addon will be used in this script.

  8. The dot command loads the file .dbfunctions into the program's memory. Now the function addon is defined for this script and available for use. It is as though you had just defined the function right here in the script.

  9. A menu is displayed with the here document. The user is asked to select a menu item.

  10. The addon function is invoked.

    Previous Section  < Day Day Up >  Next Section