Using Parameters and Variables

You saw in chapter 5 that, when Qshell finds a dollar sign preceding a parameter or variable name , it replaces the reference with the value of the indicated parameter or variable. This is known as expanding the parameter or variable.

Both the terms parameter expansion and variable expansion are used in Unix literature to refer to this process, no matter whether parameters or variables are being discussed. This chapter uses the term variable expansion because all facets of expansion are supported with variables, but one type of expansion is not supported with positional parameters.

Variable Expansion

In its simplest form, variable expansion returns the value assigned to a parameter or variable. For example, $1 and ${1} expand to the value of the first positional parameter, and $dirname and ${dirname} expand to the value of a variable whose name is dirname . However, Qshell provides operators that permit more powerful methods of variable expansion.

Table 6.1 lists the four expansion operators. Use these operators within the brace form of a variable or parameter. Before the closing brace , include the operator, and follow it with another value, whose function depends on the operator.

Table 6.1: Conditional Expansion Operators

Operator

Description

-(hyphen)

Temporarily substitute for a missing value.

+

Temporarily substitute for an existing value.

=

Assign a new value for missing value. (Not permitted with positional parameters.)

?

Generate an error if a value is missing.

The term missing value in Table 6.1 needs some explanation. You might remember from chapter 5 that there is a difference between a variable that is unset and a variable that has a null value. An unset variable is not defined, while a variable with a null value is defined, but empty.

If the operators in Table 6.1 are preceded by a colon , the term missing value means "an unset variable or a variable with the null value." Without a preceding colon, the term missing value means "an unset variable." As a rule, you will probably want to include the colon, since your consideration when using these parameter operators is more likely to be whether or not a value is missing, not why it is missing. Table 6.2 illustrates this difference more closely. Keep the following in mind to help interpret the table:

  • $ var indicates that Qshell returns the existing value of the variable.
  • Value indicates that Qshell returns the value following the operator.
  • Assign value to var means that the value following the equal sign is assigned to the variable.
  • Null indicates that Qshell uses a null value in place of the variable reference.
  • Error means that Qshell displays the message following the question mark, or a default message, and exits a noninteractive shell.
Table 6.2: Results of Variable Expansion Operators

Operator

Var Is Defined; Not Null

Var Is Null

Var Is Unset ( Undefined )

${var:-value}

$var

value

value

${var-value}

$var

null

value

${var:=value}

$var

assign value to var

assign value to var

${var=value}

$var

null

assign value to var

${var:?[message]}

$var

error

error

${var?[message]}

$var

null

error

${var:+value}

substitute value

null

null

${var+value}

substitute value

substitute value

null

The next several sections of this chapter examine each of the variable expansion operators in detail.

Temporary Substitution for a Missing Value

Use the hyphen operator to temporarily substitute a value when a variable has no value. For example, in Figure 6.1, the variable name is undefined (unset), so the first print command produces a blank line. The second print command prints the value Joe Smith because name has no value. However, the second print does not assign a value to the name variable, as the third print proves. Once the value Jack Sprat is assigned to name , the value following the hyphen is not used.


print $name


/home/JSMITH $


print ${name:-Joe Smith}


Joe Smith


/home/JSMITH $


print $name


/home/JSMITH $


name='Jack Sprat'


/home/JSMITH $


print ${name:-Joe Smith}


Jack Sprat


Figure 6.1: The presence of a colon causes null and unset values to be treated equally.

Figure 6.2 provides another example of the hyphen operator. In this case, the first print statement prints the value Bob because the variable name is undefined (unset). The second print does not print Bob because no colon precedes the hyphen operator, and name is null, but not unset.


print ${name-Bob}


Bob


/home/JSMITH $


name=


/home/JSMITH $


print ${name-Bob}


/home/JSMITH $


Figure 6.2: This example illustrates the difference between using the hyphen operator with an unset variable and a null variable.

Temporary Substitution of an Existing Value

Qshell also provides a way to temporarily override the existing value of a variable. If the variable has a non-null value, the plus operator substitutes an alternate value. Otherwise, the result of the expansion is a null value.

Consider Figure 6.3. The first two print commands print blank lines because name is undefined . The third one prints Bubba even though name has the value Bill . The last print shows that the plus operator did not change the value of variable name .


print $name


/home/JSMITH $


print ${name+Bubba}


/home/JSMITH $


name=Bill


/home/JSMITH $


print ${name+Bubba}


Bubba


/home/JSMITH $


print $name


Bill


Figure 6.3: These commands illustrate the plus operator.

Assigning a New Value for a Missing Value

Use the equal-sign operator to assign a new value to a variable with no value. That is, the variable continues to have the new value after the expansion. This type of expansion is not allowed for positional parameters.

Figure 6.4 illustrates the equal-sign operator. The variable name is unset, so the first print command leaves a blank line. The variable expansion in the second print assigns the value Suzy Q to name . The third print shows that name has kept its new value.


print $name


/home/JSMITH $


print ${name:=Suzy Q}


Suzy Q


/home/JSMITH $


print $name


Suzy Q


Figure 6.4: The equal-sign operator assigns a new value to a variable with no value.

Generating an Error If a Value Is Missing

The question-mark operator causes Qshell to issue an error message if a variable has no value. For example, the first three print commands in Figure 6.5 send messages to stderr because name is unset. The last print command does not send an error message because name has a value.


print ${name?}


qsh: 001-0021 Parameter 1$.*s is not set.


/home/JSMITH $


print ${name:?}


qsh: 001-0022 Parameter 1$.*s is not set or is null.


/home/JSMITH $


print ${name:?Name is

undefined

}


Name is

undefined



/home/JSMITH $


name='Larry, Curly and Moe'


/home/JSMITH $


print ${name:?Name is

undefined

}


Larry, Curly and Moe


Figure 6.5: These commands illustrate the question-mark operator.


Pattern Modifiers

You can use pattern modifiers to do certain types of string manipulation. Among other uses, pattern modifiers are most frequently used in scripts to manipulate variables containing file name or path name values. The four pattern modifiers are listed in Table 6.3.

Table 6.3: Pattern Modifiers

Operator

Description

#

Remove the shortest match from the beginning.

##

Remove the longest match from the beginning.

%

Remove the shortest match from the end.

%%

Remove the longest match from the end.

These operators do not modify variables. Rather, each one returns a new value you can use in Qshell commands. You can assign the value to another variable, print the value, etc.

Figure 6.6 shows each of the pattern modifiers at work on the variable var , which contains a list of consecutive letters interspersed with x 's:

  • The # operator, working from the beginning of the string, removes the smallest pattern that consists of zero or more characters followed by an x , which is abcdex .
  • The ## operator, working from the beginning of the string, removes the longest pattern that consists of zero or more characters followed by an x , which is abcdexfghxijklmnxopx .
  • The % operator, working from the end of the string, removes the smallest pattern that consists of an x followed by zero or more characters, which is xqrst .
  • The %% operator, working from the end of the string, removes the longest pattern that consists of an x followed by zero or more characters, which is xfghxijklmnxopxqrst .

print $var


abcdexfghxijklmnxopxqrst


/home/JSMITH $


print ${var#*x}


fghxijklmnxopxqrst


/home/JSMITH $


print ${var##*x}


qrst


/home/JSMITH $


print ${var%x*}


abcdexfghxijklmnxop


/home/JSMITH $


print ${var%%x*}


abcde


Figure 6.6: Each of the pattern modifiers produces a different result from the same string.

Figure 6.7 shows additional ways to use the pattern modifiers to manipulate strings. Here, the % is used to extract the directory name because it removes as few characters as possible from the end of the string. The ## operator is used to extract the file's base name because it trims all characters as possible through the last slash.


filename=/home/jsmith/temp/work1.txt


/home/JSMITH $


dir=${filename%/*}


/home/JSMITH $


print $dir


/home/jsmith/temp


/home/JSMITH $


file=${filename##*/}


/home/JSMITH $


print $file


work1.txt


/home/JSMITH $


Figure 6.7: You can use the pattern modifiers with many different Qshell commands.


Substrings

With V5R2, Qshell includes a form of variable expansion that allows you to retrieve substrings. It is similar in syntax to substring constructs found in RPG, CL, COBOL, and Java. Here is the substring syntax:


${variable:offset


[:length]

}

The offset parameter indicates the position at which to begin extracting the substring. The value indicates how far that character is offset from the beginning of the string; thus, the first character is at offset zero, not one. Another way to think of the offset is "the number of characters to skip." That is, if you skip zero characters, you begin extraction at the first byte. If the offset is longer than the string, Qshell returns the empty string. The length parameter is optional. If no length is specified, Qshell returns all characters from the offset through the end of the string.

Figure 6.8 demonstrate the use of the substring construction. In Figure 6.8, the first substring operation skips five characters, to begin extracting the remainder of the string at the sixth character. The second substring operation extracts two characters only. The remaining substring operations in Figure 6.8 show that you may use arithmetic expressions as offset and length arguments.


somevar=abcdefghij


/home/smith $


print ${somevar:5}


fghij


/home/smith $


print ${somevar:5:2

}



fg


integer i=4 len=3


/home/smith $


print ${somevar:i:len}


efg


/home/smith $


print ${somevar:i+1:len}


fgh


print ${somevar:i+1:len+1}


fghi


Figure 6.8: The first two print commands show the basic use of the substring syntax. The remaining commands use more complex syntax, involving mathematical expressions.


Substitution Expressions

V5R2 also introduced two new substitution expansion structures:


${variable/pattern/string}


${variable//pattern/string}

Notice that there is no trailing slash after the replacement string.

Figure 6.9 provides a simple example of a substitution expression.


print $name


Joe Smith


/home/JSMITH $


print ${name/Joe/Fred}


Fred Smith


Figure 6.9: The second expression substitutes Fred for Joe .

As Figure 6.10 shows, if the first slash is doubled, all instances of the longest match of the pattern are replaced . If the first slash is not doubled , only the first instance of the longest match of the pattern is replaced.


print $title


Director of the Department of Redundancy Department


/home/JSMITH $


print ${title/Department/Bureau}


Director of the Bureau of Redundancy Department


/home/JSMITH $


print ${title//Department/Bureau}


Director of the Bureau of Redundancy Bureau


Figure 6.10: In the first substitution, only the first instance of Department is changed to Bureau . In the second, both instances are changed.

A leading % in the pattern means that the pattern must match at the end of the variable, as shown in Figure 6.11. If no replacement string is given, the pattern is removed, and a leading # in the pattern means that the pattern must match at the beginning of the variable. Figure 6.12 illustrates these points.


print $dept


The Department of Redundancy Department


/home/JSMITH $


print ${dept/Department/Bureau}


The Bureau of Redundancy Department


/home/JSMITH $


print ${dept/%Department/Bureau}


The Department of Redundancy Bureau


print ${title/#Director/Supervisor}


Supervisor of the Director of the Department of Redundancy


Department


/home/JSMITH $


Figure 6.11: The percent sign in the third expansion means that the pattern must match at the end of the variable. Therefore, the second occurrence of Department is changed to Bureau , not the first.


print $title


The Director of the Director of the Department of Redundancy


Department


/home/JSMITH $


print ${title/Director of the /}


The Director of the Department of Redundancy Department


title="Director of the Director of the Department of Redundancy


Department"


/home/JSMITH $


Figure 6.12: Since no replacement string is given in the first expansion, the first instance of Director of the is removed. The second expansion changes Director to Supervisor because Director is found at the beginning of the variable.

Finally, the new substitution expansion structures can be used to strip special characters , as shown in Figure 6.13. The variable music contains leading and trailing double quotes. The expansion removes them. Notice that the double-quotes character is prefixed with a backslash in the expansion because of its special meaning to Qshell



print $music



"Le Sacre du Printemps"


/home/JSMITH $


print ${music// "/}


Le Sacre du Printemps


Figure 6.13: Substitution expansion structures can be used to remove special characters from a string.


Finding the Length of a Value

Qshell includes an expansion operator that returns the length of the value stored in a variable. Here is the syntax:


${#variable}

Figures 6.14 uses the length expansion operator in a simple expression.


print $filename


/home/jsmith/temp/bin/mydata.txt


/home/JSMITH $


print ${#filename}


32


Figure 6.14: The # preceding the variable name indicates that the length of the value of the variable is to be retrieved.

Here is the operator used in a more complex expression:

if [[ ${#1} -lt 5 ]] then
 print "First parameter must be at least five characters
 long." >&2
 exit 2
fi

In this example, if the length of the first positional parameter is less than five characters, Qshell sends an error message to the standard error device and exits the script, with an exit status of two.


Concatenating Strings

While many other languages have concatenation operators, Qshell does not. Qshell does not need a concatenation operator because concatenation is achieved by abutting values. For example, in Figure 6.15, the filename variable is assigned the value of the path variable followed by a slash and the value of the file variable.


print $path


/home/JSMITH


/home/JSMITH $


print $file


cust.csv


filename=$path/$file


/home/JSMITH $


print $filename


/home/JSMITH/cust.csv


cat $filename


1,10001,"Pye Cherry",25


1,20002,"Moss Pete",25.5


1,30003,"Dover Ben",35


1,40004,"Bellum Sara",45


2,1,"Gunn Tommy",20


2,3,"Unsaturated Polly",35


2,345,"Sox Bobby",-9.75


Figure 6.15: Concatenation is achieved by abutting values.

To include blanks in a concatenation, enclose the entire assigned string in double quotes, as shown in Figure 6.16. Single quotes would prohibit the variable expansion.


firstname=Willie


/home/JSMITH $


lastname=Makit


/home/JSMITH $


fullname="$firstname $lastname"


/home/JSMITH $



print $fullname



Willie Makit


Figure 6.16: To include blanks in a concatenation operation, enclose them in double quotes.


Numeric Constants

Qshell supports two types of numeric values: integer and floating-point (real). Integer values are of the form base#value , where base is a number between two and 36. If base# is omitted, the value is assumed to be base-10. The letters of the alphabet are used as digits in bases greater than 10, where the letter A represents 10 and the letter Z represents 35. The letters may be in either uppercase or lowercase.

Figure 6.17 contains references to numbers in various bases. The first printf command prints the values of a , b , and c in decimal format. The second printf prints the values of those variables in hexadecimal format.


a=59 b=2#1101 c=16#2F


/home/JSMITH $


printf "%d %d %d
" $a $b $c


59 13 47


/home/JSMITH $


printf "%X %X %X
" $a $b $c


3B D 2F


Figure 6.17: Integer values may be specified in any base from two to 36. The default base is 10.

Floating-point values may contain fractional portions. They are of the following form:


[+-]number[.number][exponent]

The exponent is the letter E (or e ) followed by a number. Figure 6.18 shows examples of floating-point numbers. The first assignment statement assigns values, specified in three different formats, to variables x , y , and z . The second assignment statement assigns values in yet more formats to variables a through f . The two printf commands display the assigned values as floating-point numbers.


x=2 y=4.5 z=1.7e10


/home/JSMITH $


printf "%f %f %f
" $x $y $z


2.000000 4.500000 17000000000.000000


/home/JSMITH $


a=39 b=-55 c=14.246 d=-294.8832 e=1.7e10 f=-2.55e4 g=3.93e-2


h=-7.4599e-2


/home/JSMITH $


printf "%f
" $a $b $c $d $e $f


39.000000


-55.000000


14.246000


-294.883200


17000000000.000000


-25500.000000


Figure 6.18: Floating-point numbers may be specified in several ways.

By default, arithmetic is done with integers. To enable floating-point arithmetic, use the float option of the set command. This option may be specified in two ways:


set -F


set -o float

In Figure 6.19, two variables, x and y , are multiplied, and the product is stored in z . When integer arithmetic is active, the multiplication operation fails, and z is unchanged. When floating-point arithmetic is active, the multiplication succeeds.


print $x $y $z


2 4.5 4


/home/JSMITH $


let z=x*y


let: 001-0032 Number 1.7e10 is not valid.


/home/JSMITH $


print $z


4


/home/JSMITH $


set -F


/home/JSMITH $


let z=x*y


/home/JSMITH $


print $z


9


/home/JSMITH $


Figure 6.19: Use the set utility to enable floating-point arithmetic.


Arithmetic Expressions

An arithmetic expression is a string of tokens that is interpreted as a numeric calculation. The tokens may include variable and parameter names, numeric literals, operators, and parentheses. Variable names used in arithmetic expressions do not have to be preceded by dollar signs, but it is not incorrect to include dollar signs. An unset or null variable is interpreted as zero when used in arithmetic expressions.

The supported arithmetic operators are listed in Table 6.4. They are shown in the table in order of precedence, but you may use parentheses to override their default order.

Table 6.4: Operators Allowed in Arithmetic Expressions

Operator

Description

+, -

Unary plus and minus

!, ~

Logical not, bitwise negation

*, /, %

Multiplication, division, remainder

+, -

Addition, subtraction

<<, >>

Bitwise shifts

>, <, >=, <=

Comparisons

==, !=

Equality, inequality

&

Bitwise AND

^

Bitwise exclusive OR

Bitwise OR

&&

Logical AND

Logical OR

expr?expr;expr

Conditional evaluation

=, +=, etc.

Assignment operators

You can use arithmetic expressions in the following locations:

  • In an arithmetic expansion
  • In an argument of the let utility
  • In the argument of the shift utility
  • In the arithmetic formats of the printf utility
  • In arguments of the test utility
  • In the argument of the ulimit utility
  • In the offset and length parameters of the substring variable expansion

The following example demonstrate the use of an arithmetic expression in an argument to the shift utility:

shift nb+2

The shift utility adds two to the value in variable nb and causes Qshell to shift the positional parameter list by that number of parameters. You could also have added the dollar sign, as follows (although it is not necessary):

shift $nb+2

The Let Utility

The let utility is the usual way to perform arithmetic, especially when you want to assign the result of a calculation to a variable. Here is the syntax of let :


let

arithmetic-

expression

...

You may place more than one expression on a line. The expressions are evaluated from left to right.

Figure 6.20 provides an example so you can better understand the let utility. In it, the value assigned to c is based on the result of the calculations for a and b . Before calculating a value for c , Qshell assigns values 12 and 60 to a and b respectively. For that reason, c receives a value of 5, not 2.


print $a $b $c


10 20 30


/home/JSMITH $


let a=a+2 b=b*3 c=b/a


/home/JSMITH $


print $a $b $c


12 60 5


Figure 6.20: The let utility evaluates the expressions from left to right.

You can use the let utility in several different ways. Here are a few examples, which all add one to the value of variable j :

let j+=1
let j=j+1
let "j=j+1"

Arithmetic Expansion

Arithmetic expansion allows you to embed the result of an arithmetic expression within a command. The syntax is as follows:

$((

expression

))

Simple arithmetic expansion is demonstrated in the following arithmetic expansion, which examines the remainder after first dividing variable year by four, and subsequently dividing by 100 and 400 to determine whether or not year is leap year:

if [ $((year % 4)) -eq 0 ]
then
 if [ $((year % 100)) -ne 0 -o $((year % 400)) -eq 0 ]
 then
 let count-=1
 fi
fi

In Figure 6.21, the values in positional parameters 1 and 5 are added together within the printf command.


print


10 50


/home/JSMITH $


printf "%d
" $(( + ))


60


Figure 6.21: Arithmetic expansion is used to perform arithmetic within Qshell commands.

The positional parameters $1 and $5 in Figure 20 must be preceded by dollar signs in order to distinguish them from the literals 1 and 5. However, variables do not have to be preceded by dollar signs. In Figure 6.22, the arithmetic expansion yields the same result, whether or not the length variable is preceded by a dollar sign.


size=$((length+1))


/home/JSMITH $


print $size


26


/home/JSMITH $


size=$(($length+1))


/home/JSMITH $


print $size


26


Figure 6.22: Prefixing a dollar sign to a variable name usually has no effect in arithmetic expansion.

However, in the case of assignment commands, the presence or absence of a dollar sign does matter. In Figure 6.23, for example, the second print command assigns a value to variable name because no dollar sign precedes the variable.


a=10 b=20 c=30


/home/JSMITH $


print $a $b $c $name


10 20 30


/home/JSMITH $


print $((name=999))


999


/home/JSMITH $


print $a $b $c $name


10 20 30 999


/home/JSMITH $


Figure 6.23: Dollar signs should usually be omitted when assignment statements are used in arithmetic expressions.

Compare Figure 6.23 to Figure 6.24, where variable name is preceded by a dollar sign in the echo command. The arithmetic expansion changes variable b , not variable name , because Qshell expands $name to b .


a=10 b=20 c=30 name=b


/home/JSMITH $


print $a $b $c $name


10 20 30 b


echo $(($name=999))


999


/home/JSMITH $


print $a $b $c $name


10 999 30 b


/home/JSMITH $


Figure 6.24: Prefixing the name variable with a dollar sign causes a different variable to be modified.

The Expr Utility

The only thing to remember about using the expr utility to carry out arithmetic is this: "Just say no!" Here are some reasons why:

  • Qshell starts a new subshell to run expr . Starting a subshell degrades performance. Arithmetic expansion runs in the same shell.
  • Many of the operators that expr uses have special meanings to Qshell, and therefore have to be escaped with the backslash character.
  • The expr utility handles integer arithmetic only.
  • Arguments must be separated from one another by white space.
  • The expr utility is an old one, from the Bourne shell. Newer arithmetic mechanisms have since been invented.
  • The expr utility writes the result of an expression to standard output, rather than assigning a value directly to a variable.

The expr utility was good for its time, but better ways of doing arithmetic in shells have been invented since then.


Summary

Variable expansion is the process of replacing the token that represents a parameter or variable with a value. Variable expansion allows you to temporarily assign a value to a variable, assign a value to a missing variable, manipulate strings, and extract substrings.

Arithmetic expansion provides a way for you to carry out arithmetic in Qshell scripts. Some Qshell utilities, such as let , shift , and test , also have limited arithmetic abilities .




QShell for iSeries
Qshell for iSeries
ISBN: 1583470468
EAN: 2147483647
Year: 2003
Pages: 219

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net