|
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
|