7.10. FunctionsThe Korn shell allows you to define functions that may be invoked as shell commands. Parameters passed to functions are accessible via the standard positional parameter mechanism. Functions must be defined before they are used. There are two ways to define a function, as shown in Figure 7-18.
I personally favor the second form because it looks more like the C language. To invoke a function, supply its name followed by the appropriate parameters. For obvious reasons, the shell does not check the number or type of the parameters. Here's an example of a script that defines and uses a function that takes no parameters: $ cat func1.ksh ...list the script. message () # no-parameter function. { echo hi echo there } i=1 while (( i <= 3 )) do message # call the function. let i=i+1 # increment loop count. done $ ksh func1.ksh ...execute the script. hi there hi there hi there $ _ 7.10.1. Using ParametersAs I mentioned previously, parameters are accessible via the standard positional mechanism. Here's an example of a script that passes parameters to a function: $ cat func2.ksh ...list the script. f () { echo parameter 1 = $1 # display first parameter. echo parameter list = $* # display entire list. } # main program. f 1 # call with 1 parameter. f cat dog goat # call with 3 parameters. $ ksh func2.ksh ...execute the script. parameter 1 = 1 parameter list = 1 parameter 1 = cat parameter list = cat dog goat $ _ 7.10.2. Returning from a FunctionThe return command returns the flow of control back to the caller (Figure 7-19).
When return is used without an argument, the function call returns immediately with the exit code of the last command that was executed in the function; otherwise, it returns with its exit code set to value. If a return command is executed from the main script, it's equivalent to an exit command. The exit code is accessible from the caller via the $? variable. Here's an example function that multiplies its arguments and returns the result: $ cat func3.ksh ...list the script. f () # two-parameter function. { (( returnValue = $1 * $2 )) return $returnValue } # main program. f 3 4 # call function. result=$? # save exit code. echo return value from function was $result $ ksh func3.ksh ...execute the script. return value from function was 12 $ _ 7.10.3. ContextA function executes in the same context as the process that calls it. This means that it shares the same variables, current working directory, and traps. The only exception to this is the "trap on exit"; a function's "trap on exit" executes when the function returns. 7.10.4. Local VariablesThe typeset command (described in more detail later in this chapter) has some special function-oriented facilities. Specifically, a variable created using the typeset function is limited in scope to the function in which it's created and all of the functions that the defining function calls. If a variable of the same name already exists, its value is overwritten and replaced when the function returns. This property is similar (but not identical) to the scoping rules in most traditional high-level languages. Here's an example of a function that declares a local variable using typeset: $ cat func4.ksh ...list the script. f () # two-parameter function. { typeset x # declare local variable. (( x = $1 * $2 )) # set local variable. echo local x = $x return $x } # main program. x=1 # set global variable. echo global x = $x # display value before function call. f 3 4 # call function. result=$? # save exit code. echo return value from function was $result echo global x = $x # value of global after function. $ ksh func4.ksh ...execute the script. global x = 1 local x = 12 return value from function was 12 global x = 1 $ _ 7.10.5. RecursionWith careful thought, it's perfectly possible to write recursive functions. Here are two example scripts that implement a recursive version of factorial (). The first uses the exit code to return the result and the second uses standard output to echo the result. Note these scripts are available online; see the Preface for more information. 7.10.5.1. Recursive Factorial, Using Exit Codefactorial () # one-parameter function. { if (( $1 <= 1 )) 7.10.5.2. Recursive Factorial, Using Standard Outputfactorial () # one-parameter function. { if (( $1 <= 1 )) then echo 1 # echo result to standard output. else typeset tmp # declare two local variables. typeset result (( tmp = $1 - 1 )) (( result = 'factorial $tmp' * $1 )) echo $result # echo result to standard output. fi } # echo factorial 5 = 'factorial 5' # display result. 7.10.6. Sharing FunctionsTo share the source code of a function between several scripts, place it in a separate file and then read it using the "." built-in command at the start of the scripts that use the function. In the following example, assume that the source code of one of the previous factorial scripts was saved in a file called "fact.ksh": $ cat script.ksh ...list the script. . fact.ksh # read function source code. echo factorial 5 = 'factorial 5' # call the function. $ ksh script.ksh ...execute the script. factorial 5 = 120 $ _ |