Guild Companies, Inc.  
 
Midrange Programmer - How-To Advice & Free Code
OS/400 Edition
Volume 1, Number 6 - March 28, 2002

Working with Parameters and Variables in Qshell Scripts

by Ted Holt

It's not likely that you'll write a useful Qshell script without dealing with parameters, variables, or both. Qshell would be a weak and almost worthless language if it had no mechanism to replace tokens with run-time values. If you have worked with Unix shells, you will find the same powerful data-manipulation features in Qshell. If your background is with IBM midrange machines, you'll find powerful features you never saw in CL or OCL.

I use a lot of small scripts and script fragments in this article. In the interest of simplicity, I call all of them myscript.qsh.

Parameters

When you run a script, you can pass parameters to it. The parameters are positional parameters, not keyword parameters. Parameters are separated from one another by white space, which in the case of Qshell usually means one or more blanks, since you can't type a tab character in an interactive Qshell session.

Suppose you invoked a script called myscript.qsh in the following manner:

myscript.qsh   home   jsmith

You have passed two parameters to myscript.qsh: home and jsmith.

If a parameter includes blanks, surround it with single quote (') or double quote (") marks. In this example, there are four parameters, two of which contain embedded blanks.

myscript.qsh 'New Yolk' Chicargo 'Lost Angeles' Jaxon
myscript.qsh "New Yolk" Chicargo "Lost Angeles" Jaxon

If a parameter includes a single quote or double quote mark, precede the single quote or double quote with a backslash (\).

myscript.qsh Eat at Joe\'s 
myscript.qsh 48\" "3 lbs."

In the first command, the third parameter has the value Joe's. In the second command, the first parameter is 48" (48 inches).

Retrieving the Value of a Parameter

A script can refer to parameters in one of two ways. The simpler form is $n. The other form is ${n}. In both forms, n represents a number. The Unix references that I have consulted say that n can be any number from 1 to 9. However, I have found from experimentation that Qshell allows larger numbers. I do not know how many parameters Qshell will reference in this manner, but it's at least 100. I suspect that Qshell allows 255 positional parameters, but as far as I'm concerned, 100 is infinity.

Script myscript.qsh might contain a line like this:

cd  /$1/$2

If I invoke the script as follows:

myscript.qsh   home   jsmith 

Qshell does this:

cd  /home/jsmith

There are two ways to prevent Qshell from substituting a parameter value for a parameter expression. One is to precede the dollar sign ($) with a backslash. The other is to surround the parameter expression with single quotes. For instance, consider this short script.

echo The price is \$5.
echo 'The price is $5.'
echo "The price is $5." 

If I run the script this way:

myscript.qsh I really like to eat cheese.

I get this output:

The price is $5. 
The price is $5.
The price is eat.

Notice the difference between single and double quote marks. Both preserve embedded blanks, but single quotes prevent parameter substitution.

Special Parameters

You can use several special parameters in your scripts. The Qshell reference has a complete list of them. Here are the four that I think are most useful:

$0	name of the shell script
$#	number of defined positional parameters
$*	all positional parameters
$@	all positional parameters

Note that the first one contains the numeral zero, not the letter O. I used this one in my last article.

The last two special parameters, $* and $@, differ in how parameter values are treated when enclosed in double quote marks. This is not a topic that I want to cover in this article, so for now, I'll pass along what I have been told: when in doubt, use $@.

Variables

Qshell supports internal variables. A variable name begins with a letter or underscore (_), which is followed by any combination of letters, digits, and underscores. Variables do not have data types. If you spell the same variable two different ways, Qshell will think you are using two different variables. Variable names are case sensitive; CAT, Cat, and cat are three different variables.

You create a variable by assigning a value to it, like this:

variableName=value

Leave no blanks on either side of the equal (=) sign. If you leave a blank in front of the equal sign, Qshell will look for a command or script with the name of the variable. If you leave a blank after the equal sign, Qshell undefines the variable. If the value contains blanks, enclose it in double quote marks. The double quote marks are not part of the value.

Here are some examples using a variable called thisvar:

thisvar=/home/jsmith
thisvar="/home/jsmith"
thisvar=

The first two assignments are equivalent. In both cases, the value of thisvar is /home/jsmith. After the third assignment, thisvar is no longer defined and will return a null value if referred to later in the script. If you precede a variable assignment with readonly, the script will not be able to change its value.

readonly filename=JoesData.CSV

To retrieve the value of a variable, precede its name with a dollar sign.

echo $thisvar

The echo command displays the value of variable thisvar on the screen. When you see the dollar sign, think "the value of."

You can also use unset to "undefine" a variable.

unset filename

Variable filename is no longer defined. Notice that there is no dollar sign before filename. However, consider this example:

filename=JoesData.CSV
varname=filename
# … more stuff omitted here
unset $varname

The unset will erase the value of variable filename, not variable varname. Do you see why? That's right! The dollar sign says to unset the "value of" varname, not the variable varname itself. The value of varname is filename, so filename is unset rather than varname.

Predefined Variables

Qshell defines several variables when it begins running. For instance, the PWD variable contains the name of the current directory, also called the present working directory. The LOGNAME variable holds the name of the user profile.

To see a list of these variables and the ones you have defined, type the word "set" at the Qshell command line and press Enter.

Qshell Arithmetic

There are two types of numeric values--integer and floating point (real). Integer values are of the form base#value, where base is a number between 2 and 36. If base# is omitted, the value is assumed to be base 10. The letters of the alphabet are used for digits in bases greater than 10.

thisvar=25     # decimal 25
thisvar=2#11   # binary 11 = decimal 3
thisvar=16#1A0 # hex 1A0 = decimal 416

Floating-point values are of the form [+|-] number [.number] [exponent]. The exponent is the letter E (or e) followed by a number. The following are valid floating-point values.

3
3.0
0.0125
4773.2E2
3E4
-1.25
-1.25E+09

By default, arithmetic is done with integers. To enable floating-point arithmetic, use the float option of the set command. You have two ways to specify the float option.

set  -F

or

set  -o  float

There are two ways to do arithmetic in Qshell. One method is called arithmetic expansion. Here is the syntax:

$((expression))

The expression can be a combination of data values and operators. Here are the arithmetic operators.

 
+	unary plus or addition
-	unary minus or subtraction
*	multiplication
/	division
%	remainder

If you want to multiply two numbers, for example, you would use an expression similar to either of the following:

num3=$((num1*num2))

or

num3=$(($num1*$num2))

Notice there are no spaces on either side of the equal sign.

You can also use the "let" utility to carry out arithmetic. The following is equivalent to the previous example.

let num3=num1*num2

or

let num3=$num1*$num2

Notice that the variable names on the right side of the equal sign may be preceded by a dollar sign, but they don't have to be. But if you use a parameter in an expression, you must include a dollar sign.

num3=$((num1+$1))

or

let num3=num1+$1

Changing Parameter Values

Now that you understand variables, I will return to the subject of parameters. I need to tie up some loose ends, and variables are required in one of my examples.

Parameters usually get their values from the command that starts the script, but it is possible for parameters to get values in other ways.

The "shift" utility discards one or more of the lowest-numbered parameters and renumbers the remaining, higher-numbered parameters, beginning with the first one. For example, parameter 1 is discarded, parameter 2 becomes parameter 1, parameter 3 becomes parameter 2, and so on.

The shift command takes one argument--the number of parameters to be discarded. The default is one.

shift 5 # discard the first five parameters
shift 1 # discard the first parameter
shift   # discard the first parameter

The following script portion processes a file, which is specified by a positional parameter. The script permits the user to insert a switch p before the file name.

# if no parameters were entered, display
# message and exit
if [ "$1" = "" ] 
   then echo syntax: myscript.qsh [-p] filename
        return 1 
fi
# at least one parameter was entered
pflag=off 
if [ $1 = -p ] 
  then pflag=on 
       shift 
fi 
# at this point:
#    pflag is either on or off
#    the file name is in parm 1

Thus, a user may run the script in either of two ways.

myscript.qsh  JoesData.CSV
myscript.qsh  -p   JoesData.CSV

In either case, the script uses JoesData.CSV as the filename. The second "if" command proves false in the first example, where the filename is already in the first parameter. In the second example, the filename is in the second parameter. When the second "if" proves true, the p option is saved in a variable and the shift command moves the filename from parameter 2 to parameter 1.

You can use the set command to make a script replace the parameters.

Consider this script:

echo $@
set I don\'t care for cheese.  
echo $@

If you run this script, passing it four parameters--I just love beans.--you get this output.

I just love beans.           
I don't care for cheese.      

Both echo commands display all the parameter values. The second echo shows that the parameter values have been changed.

You can use set as the opposite of the shift command. That is, the parameters are shifted to higher-numbered parameters.

echo $1 $2 $3 $4          
set "Jack & " $1 $2 $3 $4 
echo $1 $2 $3 $4 $5       

Running this script with the parameters, I like Swiss cheese, yields this output:

I like Swiss cheese.       
Jack & I like Swiss cheese.

Whereas cheese was the fourth parameter when the script began running, it was the fifth parameter when the script ended because "Jack &" is now in the first parameter.

This brings up a third method for "undefining" parameters. If you follow "set" with white space and two hyphens (-), Qshell unsets all positional parameters:

set --

readonly TheEnd=Near

I could cover more. I haven't talked about command substitution, which you can use to assign the output of a command to a variable. Nor have I dug deeply into parameter expansion. In fact, several other Qshell features are able to modify the value of a variable. Covering them would lead us too far afield. I plan to deal with those and other features in future articles.

References

  • IBM's Qshell Web site
  • Peter Scott's Unix Notes
  • Heiner's SHELLdorado
  • Sponsored By
    SOFTLANDING SYSTEMS

    Data File Reorgs Without the Downtime!

    14 GB disk space reclaimed
    =10 MINUTES downtime

    Reorganize or change your iSeries data files with virtually no downtime. Using TurnOver PDQ, one company reorganized a data file to reclaim 14 GB disk space -- with just 10 minutes of downtime! Another used PDQ to convert 43.5 million records AND process 50,000 updates -- with only 30 minutes of downtime!

    PDQ's proven technology eliminates the risk involved with traditional data file changes so you can make important changes any time without impacting business.

    Perfect for the web or any 7x24 application using iSeries data.

    For more customer stories and a free trial copy of TurnOver PDQ, visit http://www.softlanding.com/pdq/400

    THIS ISSUE
    SPONSORED BY:
    BCD Int'l
    Client Server Dev.
    COMMON
    SoftLanding Systems
    Profound Logic Software
    Midrange Blue Book
    BACK ISSUES
    TABLE OF CONTENTS
    Form Up to Learn About HTML Forms
    Recursive Calls Using Subprocedures
    Getting Started with XML
    Working with Parameters and Variables in Qshell Scripts
    Test Data Queue Applications Using Java
    CODE/400's Code/Editor: Tips and Tricks
      Newsletters | Subscribe | Advertise | About Us | Contact | Search | Home  
      Last Updated: 3/27/02
    Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved.