6 Variables

The Korn shell supports four data types: string, integer, float, and array. If a data type is not explicitly defined, the Korn shell will assume that the variable is a string.

The typeset command can also be used to assign values.

If a value is not given, the variable is set to null. Here, X is reassigned the null value:
    $ X=

6.1 Variable Attributes

Korn shell variables can have one or more attributes that specify their internal representation, access or scope, or the way they are displayed.Variables can be set to integer type for faster arithmetic operations, read-only so that the value cannot be changed, left/right justified for formatting purposes, and more. To assign a value and/or attribute to a Korn shell variable, use the following format with the typeset command:
    typeset-attribute variable=value
or
    typeset-attribute variable

Except for readonly, variable attributes can be set before, during, or after assignment. Functionally it makes no difference. Just remember that the attribute has precedence over the value. This means that if you change the attribute after a value has been assigned, the value may be affected.

6.2 Lowercase (-l) and Uppercase (-u) Attributes

These attributes cause the variable values to be changed to lower or uppercase. For example, the lowercase attribute and uppercase value ASPD are assigned to variable MYSYS:
    $ typeset —l MYSYS=ASPD
Despite the fact that MYSYS was assigned uppercase ASPD, when accessed, the value is displayed in lowercase:
    $ print $MYSYS
    aspd

This is because the attribute affects the variable value, regardless of the assignment. Variable attributes can also be changed after assignment. If we wanted to display variable MYSYS in uppercase, we could just reset the attribute:
    $ typeset —u MYSYS
    $ print $MYSYS
    ASPD

6.3 Readonly (-r) Attribute

Once the readonly attribute is set, a variable cannot be assigned another value. Here, we use it to set up a restricted PATH:
    $ typeset —r PATH=/usr/rbin
If there is an attempt to reset PATH, an error message is generated:
    $ PATH=$PATH:/usr/bin:
    /bin/ksh: PATH: is read only

Unlike other variable attributes, once the readonly attribute is set, it cannot be removed.

6.4 Integer (-i) Attribute

The integer attribute (-i) is used to explicitly declare integer variables. Although it is not necessary to set this attribute when assigning integer values, there are some benefits to it.

There is one restriction on integer variables. Once a variable is set to integer type, it can't be assigned a non-integer value:
    $ typeset —i NUM=abc
    /bin/ksh: NUM: bad number

6.5 The Float (-E, -F) Attribute

The float attributes (-E, -F) are used to declare float variables. The -E is used to specify the number of significant digits, while -F is used to specify the precision. In the following example, X is set to a float variable and assigned a value using both formats:
    $ typeset —E5 X=123.456
    $ print $X
    123.46
    $ typeset —F5 X=123.456
    $ print $X
    123.45600
The float command can also be used to declare a float variable, but does not allow for specifying the precision.

6.6 Right (-R) and Left (-L) Justify Attributes

The right and left justify attributes cause variable values to be justified within their width and are be used to format data. Here, variables A and B are set to right-justify with a field width of 7 characters. Notice that integer values are used, even though the integer attribute is not set.

    
If the field width is not large enough for the variable assignment, the value gets truncated. Variable X is assigned a seven-character wide value, but the field width is set to 3, so the first four characters are lost:
    $ typeset —R3 X=ABCDEFG
    $ print $X
    EFG

If a field width is not given, then it is set with the first variable assignment. Variable Y is assigned a three-character wide value, so the field width is set to 3.
    $ typeset —L Y=ABC
    $ print $Y
    ABC
Without explicitly resetting the field width, a subsequent assignment would be restricted to a three-character wide value:
    $ Y=ZYXWVUT
    $ print $Y
    ZYX

6.7 Autoexport (-x) Attribute

It allows you to set and export a variable in one command. Instead of
    $ typeset X=abc
    $ export X
you can do this:
    $ typeset —x X=abc
We could use this attribute to add the /lbin directory to the PATH variable and export it all in one command:
    $ typeset —x PATH=$PATH:/lbin

6.8 Removing Variable Attributes

Except for readonly, variable attributes are removed with the typeset +attribute command. Assuming that the integer attribute was set on the NUM variable, we could remove it like this:
    $ typeset +i NUM
and then reassign it a non-integer value:
    $ NUM=abc

Once the readonly attribute is set, it cannot be removed. When we try to do this with the PATH variable that was previously set, we get an error message:
    $ typeset +r PATH
    /bin/ksh: PATH: is read only
The only way to reassign a readonly variable is to unset it first, then assign a value from scratch.

6.9 Checking Variable Attributes

Attributes of Korn shell variables are listed using the typeset -attribute command. For example, to list all the integer type variables and their values:
    $ typeset —i
    ERRNO=0
    MAILCHECK=600
    PPID=177
    RANDOM=22272
    SECONDS=4558
    TMOUT=0

To list only the names of variables with a specific attribute, use the typeset +attribute command.

6.10 More with Variables

You can do other things with variables, such as assign them the value of another variable, the output of a command, or even the contents of a file.

Variables can be assigned command output using this format:
    variable=$(command)
or
    variable=`command`

The second format is provided for compatibility with the Bourne shell. Here, UCSC is set to its internet ID by assigning the output of the grep and cut commands:
    $ UCSC=$(grep UCSC /etc/hosts | cut —f1 —d" ")
    $ print $UCSC
    128.114.129.1

Variables can also be assigned the contents of files like this:
    variable=$(<file)
or
    variable=`cat file`
The first format is equivalent to variable=$(cat file). The second format is much slower, but is provided for compatibility with the Bourne shell.

nameref variable is a synonym for another variable and will always have the same value as its associated variable They are created using the following formats:
    nameref nameref_variable=variable
or
    typeset -n nameref_variable=variable
For example:
    $ X=abc
    $ nameref Y=X
    $ print $X
    abc
    $ print $Y
    abc

6.11 Unsetting Variables

Variable definitions are removed using the unset command. This is not the same as being set to null.

Unsetting either the base or nameref variable will unset both variables.


7 Special Parameters


7.1 The ? Parameter

The ? parameter contains the exit status of the last executed command. In this example, the date command is executed. It ran successfully, so the exit status is 0:
    $ date +%D
    05/24/96
    $ print $?
    0
When used with a pipe, $? contains the exit status of the last command in the pipeline.

7.2 The $ Parameter

The $ parameter contains the process id of the current shell.
    $ print $$
    178

It is useful in creating unique file names within Korn shell scripts.
    $ touch $0.$$
    $ ls *.*
    ksh.218

7.3 Other Special Parameters

The - parameter contains the current options in effect. The output of the next command shows that the interactive and monitor options are enabled:
    $ print $—
    im

To display the error number of the last failed system call, use the ERRNO variable. Here, an attempt to display a non-existent file returns an error, so ERRNO is checked for the error number:
    $ cat tmp.out
    tmp.out: No such file or directory
    $ print $ERRNO
    2
This is system dependent, so it may not be available on your system. Check your documentation or /usr/include/sys/errno.h for more information.

8 Variable Expansion

Variable expansion is the term used for the ability to access and manipulate values of variables and parameters. Basic expansion is done by preceding the variable or parameter name with the $ character. This provides access to the value.
    $ UULIB=/usr/lib/uucp
    $ print $UULIB
    /usr/lib/uucp

Other types of expansion can be used to return portions or the length of variables, use default or alternate values, check for mandatory setting, and more.

For the sake of convenience, the term variable will refer to both variables and parameters in the following sections that discuss variable expansion.


8.1 $variable, ${variable}

This is expanded to the value of variable. The braces are used to protect or delimit the variable name from any characters that follow. The next example illustrates why braces are used in variable expansion. The variable CA is set to ca:
    $ CA=ca

What if we wanted to reset CA to california? It could be reset to the entire value, but to make a point, let's try using the current value like this:
    $ CA=$CAlifornia
    $ print $CA
    $

Nothing is printed, because without the braces around the variable CA, the Korn shell looks for a variable named $CAlifornia. None is found, so nothing is substituted. With the braces around variable CA, we get the correct value:
    $ CA=${CA}lifornia
    $ print $CA
    california

Braces are also needed when attempting to expand positional parameters greater than 9. This ensures that both digits are interpreted as the positional parameter name.


8.2 ${#variable}

This is expanded to the length of variable. In this example, X is set to a three-character string, so a length of 3 is returned:
    $ X=abc
    $ print ${#X}
    3
Whitespace in variable values is also counted as characters.


8.3 ${variable:-word}, ${variable-word}

This is expanded to the value of variable if it is set and not null, otherwise word is expanded. This is used to provide a default value if a variable is not set. In the following example, the variable X is set to abc. When expanded using this format, the default value abc is used:
    $ X=abc
    $ print ${X:—cde}
    abc
After X is unset, the alternate value cde is used:
    $ unset X
    $ print ${X:—cde}
    cde
Notice that the value of X remains unchanged:
$ print $X
$

Let's say we needed a command to get the user name. The problem is that some people have it set to USER, while others have it set to LOGNAME. We could use an if command to check one value first, then the other. This would be quite a few lines of code. Or we could use this form of variable expansion to have both values checked with one command. Here, if USER is set, then its value is displayed, otherwise the value of LOGNAME is displayed.
    $ print USER=$USER, LOGNAME=$LOGNAME
    USER=anatole, LOGNAME=AO
    $ print ${USER:—${LOGNAME}}
    anatole
Now we unset USER to check and make sure that LOGNAME is used:
    $ unset USER
    $ print ${USER:—${LOGNAME}}
    AO

But what if both USER and LOGNAME are not set? Another variable could be checked like this:
    $ unset USER LOGNAME
    $ print ${USER:-${LOGNAME:-USER and LOGNAME not set!}}
    USER and LOGNAME not set!
Or
$ print ${USER—${LOGNAME:—$(whoami)}}
anatole

Remember that the alternate value is only used and not assigned to anything. The other format, ${variable-word}, causes the variable value to be used, even if it is set to null:
    $ typeset X=
    $ print ${X-cde}
    $


8.4 ${variable:=word}, ${variable=word}

This is expanded to the value of variable if set and not null, otherwise it is set to word, then expanded. In contrast to the variable expansion format from the previous section, this format is used to assign a default value if one is not already set. In the next example, the variable LBIN is set to /usr/lbin. When expanded using this format, the default value /usr/lbin is used:
    $ LBIN=/usr/lbin
    $ print ${LBIN:=/usr/local/bin}
    /usr/lbin

After LBIN is unset, this form of variable expansion causes LBIN to be assigned the alternate value, /usr/local/bin:
$ unset LBIN
$ print ${LBIN:=/usr/local/bin}
/usr/local/bin

Command substitution can also be used in place of word. This command sets the SYS variable using only one command:
    $ unset SYS
    $ print ${SYS:=$(hostname)}
    aspd

The other format, ${variable=word}causes the variable value to be used, even if it is set to null. Here LBIN is not assigned an alternate value. If := was used instead of =, then LBIN would be set to /usr/local/bin:
    $ LBIN=
    $ print ${LBIN=/usr/local/bin}
    $


8.5 ${variable:?word}, ${variable:?}; ${variable?word}, ${variable?}

This is expanded to the value of variable if it is set and not null, otherwise word is printed and the Korn shell exits. If word is omitted, "parameter null or not set" is printed. This feature is often used in Korn shell scripts to check if mandatory variables are set. In this example, variable XBIN is first unset. When expanded, the default error is printed:
    $ unset XBIN
    $ : ${XBIN:?}
    /bin/ksh: XBIN: parameter null or not set

You could also provide your own error message:
    $ print ${XBIN:?Oh my God, XBIN is not set!}
    /bin/ksh: XBIN: Oh my God, XBIN is not set!

The other formats, ${variable?word} and ${variable?}, cause the variable value to be used, even if it is set to null.


8.6 ${variable:+word }, ${variable+word }

This is expanded to the value of word if variable is set and not null, otherwise nothing is substituted. This is basically the opposite of the ${variable:-word} format. Instead of using word if variable is not set, word is used if variable is set. In the first example Y is set to abc. When expanded, the alternate value def is displayed because Y is set:
    $ Y=abc
    $ print ${Y:+def}
    def

Here, Y is unset. Now when expanded, nothing is displayed:
    $ unset Y
    $ print ${Y:+def}
    $

Like the ${variable:-word} format, the alternate value is only used and not assigned to the variable. Y is still set to null:
    $ print $Y
    $

The other format, ${variable+word}, causes the variable value to be used, even if it is set to null:
    $ Y=
    $ print ${Y+def}
    def

8.7 ${variable#pattern}, ${variable##pattern}

This is expanded to the value of variable with the smallest (#) or largest (##) part of the left matched by pattern deleted. What these expansion formats allow you to do is manipulate substrings. To demonstrate the basic functionality, X is set to a string that contains a recurring pattern: abcabcabc.
    $ X=abcabcabc

When expanded to return the substring that deletes the smallest left pattern abc, we get abcabc:
    $ print ${X#abc*}
    abcabc

while the substring that deletes the largest left pattern abc is abcabcabc, or the entire string:
    $ print ${X##abc*}
    $

We could use this concept to implement the Korn shell version of the UNIX basename command. The pattern in this command causes the last directory to be returned if variable X is set to a full pathname:
    $ X=/usr/spool/cron
    $ print ${X##*/}
    cron

8.8 ${variable%pattern}, ${variable%%pattern}

This is expanded to the value of variable with the smallest (%) or largest (%%) part of the right matched by pattern deleted. It could also be used to display file names without their .suffixes:
    $ X=file.Z
    $ print ${X%.*}
    file

The pattern in this command causes it to act like the UNIX dirname command. Everything except the last directory is returned if variable X is set to a full pathname.
    $ X=/usr/spool/cron
    $ print ${X%/*}
    /usr/spool

8.9 ${variable//pattern1/pattern2}, ${variable/pattern1/pattern2}; ${variable#pattern1/pattern2},${variable/%pattern1/pattern2}

The Korn shell supports four search and replace operations on variables. This example changes all occurrences of abc in X to xyz:
    $ X=abcabcabc
    $ print ${X//abc/xyz}
    xyzxyzxyz
while this one only changes the first occurrence of abc in X to xyz:
    $ X=abcabcabc
    $ print ${X/abc/xyz}
    xyzabcabc
See Table 3.6 for detailed explanation of the other formats.


8.10 ${variable:start}, ${variable:start:length}

This format returns a substring. The first returns variable from character position start to end, while the second returns length characters from variable from character position start to end. For example, this returns the first 3 characters of X:
    $ X=abcdefghij
    $ print {$X:0:3}
    abc
while this example returns the value of X starting at character position 5:
    $ X=abcdefghij
    $ print {$X:5}
    fghij


9 Array Variables

Arrays can have a maximum of 4096 elements. Array subscripts start at 0 and go up to 4096 (or the maximum element minus one). Any variable can become a one-dimensional array by simply referring to it with a subscript.

9.1 Array Variable Assignments & Declarations

Arrays can be assigned values by using normal variable assignment statements, the set -A command, or the typeset command:
        variable[0]=value variable[1]=value . . . variable[n]=value
or
        set -A variable value0 value1 . . . valuen
or
        typeset variable[0]=value variable[1]=value . . .  variable[n]=value

The only difference between the formats, is that with the set command format, the values are assigned to the array variable sequentially starting from element zero. In the other formats, the array elements can be assigned values in any order.

Not all the elements of an array need to exist. You can assign values to non-successive elements of an array.


9.2 Array Variable Expansion


Array variables are expanded in the same manner as normal variables and parameters: using the $ character. Without a subscript value, an array variable refers to the first element, or element 0.

To access the value of a specific array variable element use a subscript. Array variable names and subscripts must be enclosed in braces for proper expansion:
    $ print ${DAY[3]} ${DAY[5]}
    Thu Sat

All the elements of an array can be accessed by using the * or @ as the subscript value. They both return the same value.

The number of elements of an array variable is returned by using the # in front of the array variable name and using * or @ as the subscript value.

To get values for a subset of an array, use this format:
        ${variable[*]:start_subscript:num_elements}
or
        ${variable[@]:start_subscript}

Arithmetic expressions can be used to return a subscript value. Variable expansion can also be used to generate a subscript value.


9.3 Array Variable Attributes

Arrays can also be declared, and assigned values and attributes with the typeset command:
                typeset -attribute variable[0]=value variable[1]=value . . .
Once set, attributes apply to all elements of an array. This example sets the uppercase attribute for the DAY array variable using the typeset -u command:
        $ typeset —u DAY
Now all the element values are displayed in upper case:
        $ print ${DAY[*]} #Pay attention to usage.
        MON TUE WED THU FRI SAT SUN
Array element attributes can be set before or after assignment.


9.4 Array Variable Reassignments

Besides using regular array-element[n]=value or typeset arrayelement[n]=value syntax to reassign values, array variables can also have their values reassigned with the set +A command:
set +A variable value0 value1 . . .


9.5 Associative Arrays

Associative arrays use string subscripts rather than integer subscripts. Associative arrays are declared using this format:
                typeset -A variable
where 
variable is the name of the associative array. Additional arguments can be given to the typeset command to specify a data type. For example, we can create an associative array to store some exchange rates:
    $ typeset -AE exchange_rate
    $ exchange_rate["DM"]=1.7
    $ exchange_rate["FF"]=.15
    $ exchange_rate["AS"]=.04

To display a list of associative array subscripts:
                ${!variable[*]}  or  ${!variable[@]}
To display the values for all or parts of an associative array:
        ${!variable[subscript]}
For example, all and a specific exchange rate is displayed here:
    $ print ${!exchange_rate[*]}
    0.15 1.7
    $ print "The DM exchange rate is:${exchange_rate[DM]}"
    1.7


10 Compound Variables

Compound Variables is a meta-datatype which is a group of related values. The syntax for declaring compund variables is:
    compound_variable=(
            
[datatype] field1[=value]
                . . .
           
 [datatypefieldn[=value]
            
)


The syntax to display the value of a compound variable field is:
                ${compound_variable.field}


11 Quoting

There are three types of quotes: single quotesdouble quotes, and back quotes. Single and double quotes are similar, except for the way they handle some special characters. Back quotes are used for command output assignment.


11.1 Single Quotes

Single quotes are also used to hide the meaning of special characters like $, *, /, !, ", ` and /. Any characters between single quotes, except another single quote, are displayed without interpretation as special characters:
    $ print '* $ / ! ` / "'
    * $ / ! ` / "

Variable and command substitution does not take place within single quotes (because $ and `` lose their special meaning). If you want to access the value of a variable, use double quotes instead of single quotes (discussed in the next section).

Variables can be set to null with single quotes:
    $ X=''
Single quotes are also used to assign values to aliases and trap commands, and prevent alias substitution, but we'll get to that later.


11.2 Double Quotes

Double quotes are like single quotes, except that they do not remove the meaning of the special characters $, `, and /. This means that variable and command substitution is performed.
    $ DB="$HOME:`pwd`"
    $ print $DB
    /home/anatole:/tmp

Double quotes also preserve embedded whitespace and newlines. Here are some examples:
    $ print "Line 1
    > Line 2"    #The > is the secondary prompt, and is displayed whenever the Korn shell needs more input.
    Line 1
    Line 2
    $ print "A        B"
    A        B

In this case, it waits for the closing double quote:
    $ ADDR="ASP,Inc
    > PO Box 23837
    > San Jose CA 95153 USA
    > (800)777-UNIX * (510)531-5615"
Without double quotes around ADDR, we get this:
    $ print $ADDR
    ASP,Inc PO Box 23837 San Jose CA 95153 USA (800) 777-
    UNIX * (510)531-5615
Not quite what we wanted. Let's try it again:
    $ print "$ADDR"
    ASP,Inc
    PO Box 23837
    San Jose CA 95153 USA
    (800)777-UNIX * (510)531-5615

There are also other uses for double quotes. You can set a variable to null:
    $ NULL=""
    $ print $NULL
    $
or display single quotes.
    $ print "'This is in single quotes'"
    'This is in single quotes'
If you really wanted to display the $, `, /, or " characters using double quotes, escape them with a backslash like this:
    $ print "/$HOME is set to $HOME"
    $HOME is set to /home/anatole
    $ print "/`=back-quote //=slash /"=double-quote"
    `=back-quote /=slash "=double-quote


11.3 Back Quotes

Back quotes are used to assign the output of a command to a variable. This format, from the Bourne shell, is accepted by the Korn shell but considered obsolescent. This command sets the variable SYS to the system name:
    $ SYS=`uuname —l`
    $ print $SYS
    aspd


12 Command History File

The Korn shell stores the commands that you enter at your terminal in a file, called the command history file. This file is specified by the HISTFILE variable. If not set, the default is $HOME/.sh_history.

The number of commands accessible via the command history file is specified by the HISTSIZE variable. If not set, the last 128 commands are saved, starting from your most recent command.

There are two ways to access the command history file: using the fc command, or the in-line editor.


13 The fc Command

The fc command allows you to list, or edit and re-execute history file commands. The fc command also allows you to manipulate the history file using your own choice of editors.

13.1 Displaying the Command History File

The format for displaying the command history file with the fc -l command is:
        fc -l[nr] [ range ]
where the -n option causes the command numbers to not be  displayed, and the -r option specifies reverse order (latest commands first). The range of commands to list is given as:
n1 [n2]:     display list from command n1 to command n2. If n2 is not specified, display all the commands from current command back to command n1.
-count:     display the last count commands string display all the previous commands back to the command that matches.
string:     If no range argument is given, the last sixteen commands are listed.

If no range argument is given, the last sixteen commands are listed. Let's look at the last five commands:
    $ fc -l -5
    250 set
    251 vi /etc/env
    252 . /etc/env
    253 set
    254 alias
    255 functions
The history command is equivalent to fc -l. The last command could also be given like this. Notice that the order is reversed.
    $ history —r —5
    255 functions
    254 alias
    253 set
    252 . /etc/env
    251 vi /etc/env
    250 set
By using a string instead of a count argument, we could search backward for a specific command.
    $ history —r set
    258 fc —lr set
    257 fc —ln —10
    256 fc —l 250 265
    255 functions
    254 alias
    253 set
The argument set could also be given as s, or se, since partial strings are also matched. This means that the string f would match functions and fc, while fu would only match functions.


13.2 Editing the Command History File

Besides displaying the command history file, it can also be edited using the fc command with the following format:
                fc [-e editor] [-r] [range]
or
                fc -e - [old=new] [command]
where the -e editor option is used to specify an editor. If not given, the value of the FCEDIT variable is used, and if not set, the default /bin/ed is used. The -r option reverses the order of the commands, so that the latest commands are displayed first.

Using r, the last command could also be given as: 
    $ r 173

The substitution feature is used to make minor changes to a previous command. Let's start with print Hello:
    $ print Hello
    Hello
We could change Hello to something else like this.
    $ r Hello=Goodbye print
    print Goodbye
    Goodbye


14 Job Control

Job control allows programs to be stopped and restarted, moved between the foreground and background, their processing status to be displayed, and more. To enable the job control feature, the monitor option must be enabled with the set command:
                $ set —o monitor
or
                $ set —m
This can be put into the .profile file so that job control is automatically enabled at login.

14.1 Manipulating Jobs
Jobs running in the foreground are suspended by typing Ctl-z (Control-z). So instead of waiting for the long-running split command to complete, it is interrupted using Ctl-z:
    $ split —5000 hugefile

    Ctl-z
    [3] + Stoppedsplit —5000 hugefile
    $

Stopped and backgrounded jobs are brought back into the foreground with the fg command. If no argument is given, the current (most recently stopped or backgrounded) job is used. The stopped split job is brought back into the foreground with fg:
    $ fg
    split —5000 hugefile
or 
    $ fg %3

Stopped jobs are put into the background with the bg command.


14.2 Checking Job Status

The status and other information about all jobs is displayed using the jobs command. The jobs -l command shows the same information, along with the process ids, while jobs -p only gives you the process ids.
    $ jobs —l
    [3] + 466 Stopped split —5000 hugefile
    [2] — 465 Running find / —name core —print &
    [1] 463 Running sleep 25 &

Stopped or background jobs are terminated with the kill command.

You can make the Korn shell wait for some or all background jobs to complete with the wait command. If no argument is given, the Korn shell waits for all background jobs to complete.


14.3 Job Control

Jobs being executed in the background are prevented from generating output by setting stty tostop. Let's run the find job again with the tostop option enabled:
    $ stty tostop
    $ find / —name core —print &
    [2] 1460
The stty tostop command can be put into your profile file so that background job output is by default disabled.


The nohup command can also be used to direct output from background jobs. It causes standard output and standard error to be automatically sent to nohup.out, or whatever file you give it. One added benefit. The nohup command will keep jobs running, even if you log out. Here we run the find job again using nohup. First we need to enable background job output:
    $ stty —tostop
    $ nohup find / —name core —print &
    [2] 1469
    $ wait
    Sending output to 'nohup.out'
    [2] + Done nohup find / —name core —print &
The find job output is in nohup.out:
    $ cat nohup.out
    /usr/lbin/core
    /home/anatole/bin/core

14.4 Job Names

15 Performing Arithmetic

All of the operators from the C programming language (except ++, --, and ?:) are now supported by the Korn shell.



15.1 The let Command

Integer arithmetic can be done with the let command and arithmetic expressions. The format for the let command is:
                let  "arithmetic-expression"
where arithmetic-expressions can contain constants, operators, and Korn shell variables. Double quotes are used with arithmetic expressions that contain white space or operators that have special meaning to the Korn shell.

Notice that in arithmetic expressions, regular variables can be referenced by name only, and do not have to be preceded by $ for substitution to be performed. Both
    $ let "X=X + 1"
and
    $ let "X=$X + 1"
are equivalent. The first format is preferred because parameter expansion does not have to be performed.

15.2 The ((...)) Command

The ((...)) command is equivalent to the let command, except that all characters between the (( and )) are treated as quoted arithmetic expressions. This is more convenient to use than let, because many of the arithmetic operators have special meaning to the Korn shell. The following commands are equivalent:
    $ let "X=X + 1"
and
    $ ((X=X + 1))



15.3 Declaring Integer Variables

As with ordinary variables, integer variables need not be declared. A variable can simply be given an integer value, and then used in an arithmetic expression. However, variables can be explicitly declared integer type by using the typeset -i command. There is also another command called integer, which is equivalent to typeset -i.

Arithmetic can be performed directly on integer variables without using the let or ((...)) commands, as long as the integer value is being assigned a value. In other words, you can do this:
    $ integer DAYS="4 + 3"
instead of
    $ ((DAYS=4 + 3))
or
    $ let "DAYS=4 + 3"


15.4 Arithmetic Constants

The format for arithmetic constants is:
        number
or
        base#number
where base is a whole number between 2 and 36, and number is any non-negative integer. If not specified, the default base is 10. The arithmetic base of a variable can be set with the typeset -in command, or by prepending base# to the value. In this example, variable X is set to 5 in base 2 using both formats:
    $ typeset —i2 X=5
or
    $ typeset —i X=2#101     #Note here 101 denotes 5 in decimal. 

If you want to display the value of X in another base, just reset the base with the typeset -in command. Here it is reset to base 3:
    $ typeset —i3 X
    $ print $X
    3#12


15.5 Random Numbers

The Korn shell provides a special variable, RANDOM, which is used to generate random numbers in the range from 0 to 32767.

You can also initialize a sequence of random numbers by setting RANDOM to a value. Here, RANDOM is set to 7. When subsequently accessed, the values 2726 and 18923 are returned:
    $ RANDOM=7
    $ print $RANDOM
    2726
    $ print $RANDOM
    18923
When RANDOM is reset to 7 again, the same numbers are returned:
    $ RANDOM=7
    $ print $RANDOM
    2726
    $ print $RANDOM
    18923
If RANDOM is unset, the special meaning is removed, even if reset.


16 The Environment