|
|
![]() |
|
|
Qshell Functions by Ted Holt Most computer languages have some sort of subroutine structure. RPG has subroutines and subprocedures. COBOL has paragraphs. FORTRAN and Visual Basic have functions and subroutines. C and Java have functions only. And on it goes. The Qshell scripting language, which runs under OS/400, also allows for internal functions. In this article, I'm going to show you how to write and use functions in Qshell scripts.
Function Syntax Many Unix shells have two acceptable ways of defining functions in scripts. Under V5R1 and previous releases, Qshell only supports one of those forms. V5R2 supports both. First, the function syntax that doesn't work in Qshell prior to V5R2.
function function-name {
. . . commands
}
The function declaration begins with the word function, followed by the function name and an opening brace. Following this is one or more lines of commands. The function declaration ends with a line containing a closing brace. Here's the other syntax, the one that all releases of Qshell accept.
function-name( ) {
. . . commands
}
If you prefer, you can put the opening brace on a line of its own.
function-name( )
{
. . . commands
}
Now it's time for an example. Here's a function called lastchar. It copies the last character of a character string into the variable clast. If the character string is empty, it assigns an empty (null) value to clast.
lastchar() {
local length=${#1}
if [ $length -gt 0 ]
then clast=$(echo $1 | cut -c $length)
else
clast=''
fi
}
Here's how it works. The value that is passed to lastchar is referred to within lastchar as $1. Keep in mind that this is not the first argument passed to the script, but the first argument passed to lastchar. The first line places the length of the argument into a local variable called length. A local variable is one that is defined only within the function. If the length is greater than zero, then at least one character was passed to the function. The then part of the if structure kicks in. The echo command sends the value of the first argument into the cut command, which extracts one character beginning at the position specified by the length variable. This is the last character in the string. The echo and cut pair are surrounded by parentheses, which are preceded by a dollar sign. This is called command substitution, and it directs the output of the commands inside the parentheses into variable clast. Invoking a Function To invoke a function, use the function name, followed by any arguments to be passed to the function. Separate the function name from the first argument, and the arguments from one another, with white space. Here's how to invoke the lastchar function and pass the value of variable somevar to it. lastchar $somevar If somevar has the value mydata, lastchar places an "a" in the clast variable. You must define a function before invoking it. For this reason, it is customary to place function declarations at the beginning of a shell script. Input to Functions Like a script, a function can receive positional parameters, which are referred to with a dollar sign ($) followed by a positive number. Qshell does not confuse the positional parameters of a function with the positional parameters of other functions or of the script itself. Here's a script I'll refer to as myscript.qsh.
#! /bin/qsh
funk_shun() {
echo "Parameter 1 of funk_shun is $1"
}
script=$(basename $0)
echo "Parameter 1 of script $script is $1"
funk_shun 'No way Jose'
echo "Parameter 1 of script $script is $1"
Notice that both echo statements output the value of the first positional parameter. What do you think happens if I use the following command to run the script? myscript.qsh Yes! I'll tell you what happens. The following is sent to the standard output device (stdout). Parameter 1 of script myscript.qsh is Yes! Parameter 1 of funk_shun is No way Jose Parameter 1 of script myscript.qsh is Yes! Special parameters also have appropriate values within a function. For example, the special parameter $# used in the non-function portion of a script returns the number of arguments passed to the script. When $# is used in a function, it returns the number of arguments passed to the function. The special parameter $0 is an exception. It does not have a special value within a function. Whether it's used in a function or in the non-function section of a script, $0 always returns the script name. Output from Functions Since Qshell functions are called functions, not subroutines, you probably already suspect that there is some way for a function to return data, and there is. A function returns an exit status between 0 and 255 inclusive. By convention, an exit status of zero indicates that a function completed normally. Whether or not you do anything with the return code is your business. Use the return utility if you want to assign the exit status. If you do not assign the exit status, the exit status is the exit status of the last-executed command.
backup_file() {
if [ -z $1 ]
then return 41
elif [ ! -e $1 ]
then return 42
elif [ ! -f $1 ]
then return 43
else
cp $1 $1.copy
fi
}
In the above example, the exit status may be any of several values:
See my discussion of the exit status in the article "Success or Failure in Qshell Scripts" for more information. Even though the exit and return utilities both set the exit status, do not confuse the two. If you use the exit utility in a function, Qshell will shut down the entire script. Because the function returns an exit status, you can code a function call wherever a condition is allowed. If you need to check the status code for a certain value, use the $? parameter in the caller. The following example illustrates both of these concepts. if backup_file $1 then : else echo "Backup of file $1 failed; exit status was $?." >&2 fi If the backup_file function succeeds, nothing happens. If it fails, a message is sent to stderr. I've told you why a Qshell function is called a function and not a subroutine. Now I will tell you how to get more useful output from a function. One way is to modify global variables. Do you remember the lastchar function?
lastchar() {
local length=${#1}
if [ $length -gt 0 ]
then clast=$(echo $1 | cut -c $length)
else
clast=''
fi
}
It modifies the global variable clast with the last character of a string. Another common way to retrieve data from a function is to write to stdout. You can use the command substitution technique to direct the output to a variable. Here's a partial script that contains a function called firstchar, whose job is to return the first character of a string.
firstchar() {
echo "$1" | cut -c 1
}
echo "Type g and press Enter to continue."
read input
answer=$(firstchar "$input")
if [ "$answer" != g ]; then
exit 1
fi
# user typed g
# script continues here . . . . .
In the firstchar function, the echo directs the value of the first argument into the cut command, which writes the first character to stdout. Look at the main code. Qshell asks the user to type the letter "g" and press Enter. Whatever the user types is stored in variable input. The firstchar function is invoked within a command substitution expression, which sends the output of firstchar into variable answer. If the first character is a lowercase "g," the script continues; otherwise it ends with an exit status of 1. The user can type anything that begins with a "g" in order to continue the script. There's Fun in Function Now you know how to write functions. Use them to develop utility routines. Use them to break big scripts down into manageable pieces. Just use them. References Advanced Bash-Scripting Guide: Functions Advanced Bash-Scripting Guide: Subshells Peter Scott's Unix Notes: Shell Scripts--Procedures UNIX Shell Script Tutorials & Reference
|
Editors
Contact the Editors |
|
Last Updated: 9/26/02 Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved. |