## Part I    Programming Perl

### 1 Perl Data Types

#### 1.1 Funny Characters

Type Character Example Is a name for:
Scalar cents An individual value (number or string)
Array @ @large A list of values, keyed by number
Hash % %interest A group of values, keyed by string
Subroutine & &how A callable chunk of Perl code
Typeglob * *struck Everything named struck

#### 1.2 Singularities

Strings and numbers are singular pieces of data, while lists of strings or numbers are plural. Scalar variables can be assigned any form of scalar value: integers, floating-point numbers, strings, and even esoteric things like references to other variables, or to objects.

As in the Unix shell, you can use different quoting mechanisms to make different kinds of values. Double quotation marks (double quotes) do variable interpolation and backslash interpolation (such as turning /n into a newline) while single quotes suppress interpolation. And backquotes (the ones leaning to the left) will execute an external program and return the output of the program, so you can capture it as a single string containing all the lines of output.

$answer = 42; # an integer$pi = 3.14159265; # a "real" number
$avocados = 6.02e23; # scientific notation$pet = "Camel"; # string
$sign = "I love my$pet"; # string with interpolation
$cost = 'It costs$100'; # string without interpolation
$thence =$whence; # another variable's value
$salsa =$moles * $avocados; # a gastrochemical expression$exit = system("vi $file"); # numeric status of a command$cwd = pwd; # string output from a command

And while we haven't covered fancy values yet, we should point out that scalars may also hold references to other data structures, including subroutines and objects.

$ary = /@myarray; # reference to a named array$hsh = /%myhash; # reference to a named hash
Enter choice: $Notice that the command prompt was displayed following the argument, and not on the next line. ### 19.2 print Options ### 19.3 The exec Command The exec command is used to perform I/O redirection with file descriptors 0 through 9 using this format: exec I/O-redirection-command The I/O redirection performed by the exec command stays in effect until specifically closed, changed, or if the script or shell terminates. Here, file redir.out is opened as file descriptor 5 for reading and writing:$ exec 5<>redir.out
Now the print command writes something to file descriptor 5:
$print —u5 "This is going to fd 5" and the cat command reads from it:$ cat <&5

This is going to fd 5
To finish up, we use another exec to close file descriptor 5:
$exec 5<&— Standard input can be taken from a file like this: exec 0<file Commands could be read in from file, and it would be almost as if you typed them at your terminal. ### 19.4 The read Command The read command is used to read input from a terminal or file. The basic format for the read command is: read variables where a line is read from standard input. Each word in the input is assigned to a corresponding variable, so the first variable gets the first word, the second variable the second word, and so on. Here, "This is output" is read in to the variables X, Y, and Z. The first word of the input is This, so it is assigned to the first variable X. The second word is is, so it is assigned to the second variable Y. The third word is output, so it is assigned to Z.$ print "This is output" | read X Y Z
$print$X
This
$print$Y
is
$print$Z
output

If there aren't enough variables for all the words in the input, the last variable gets all the remaining words.
This command is the same as the last one, except that an extra string "again" is given.
$print "This is output again " | read X Y Z$ print $X This$ print $Y is$ print $Z output again #### 19.4.1 Reading Input from Files The read command by itself will only read one line of input, so you need a looping command with it. To read in the contents of a file, use this format: exec 0<file while read variable do commands done The exec command opens file for standard input, and the while command causes input to be read a line at a time until there is no more input. Here is an alternate format that will also work for reading input from files: cat file | while read variable do commands done On the systems tested, the exec format for reading input from files was about 40-60 times faster than the last version above. #### 19.4.2 The IFS Variable The read command normally uses the IFS (Internal Field Separator) variable as the word separators. The default for IFS is space, tab, or snewline character, in that order, but it can be set to something else. By setting IFS to :, the fields in the /etc/passwd file could be read into separate variables.$ cat ifs_test
IFS=:
exec 0</etc/passwd
while read -r NAME PASS UID GID COMM HOME SHELL
do
print "Account name= $NAME Home directory=$HOME
Login Shell= $SHELL" done ### 19.4.3 Reading Input Interactively The read command allows input to be read interactively using this format: read name?prompt where prompt is displayed on standard error and the response is read into name. So instead of using two commands to display a prompt and read the input:$ print —n "Enter anything: "
$read ANSWER The same thing can be done with one command.$ read ANSWER?"Enter anything: "
Enter anything: ANYTHING
$print$ANSWER
ANYTHING

If no variables are given to the read command, the input is automatically assigned to the REPLY variable. Here, ANYTHING is read into REPLY:
$print ANYTHING | read$ print $REPLY ANYTHING ## 20 Miscellaneous Programming Features ### 20.1 The . Command The . command reads in a complete file, then executes the commands in it as if they were typed in at the prompt. This is done in the current shell, so any variable, alias, or function settings stay in effect. It is typically used to read in and execute a profile, environment, alias, or functions file. Here the .profile file is read in and executed:$ . .profile

The following example illustrates the difference between executing files as Korn shell scripts and reading/executing them using the .command. The .test file sets the variable X:
$cat .test X=ABC When the .test file is executed as a Korn shell script, variable X is not defined in the current environment, because scripts are run in a subshell:$ ksh .test
$print$X
$After the .test file is read in and executed using the . command, notice that the variable X is still defined:$ . .test
$print$X
ABC
The standard search path, PATH, is checked if the file is not in the current directory.

### 20.2 Functions

Functions are most efficient for commands with arguments that are invoked fairly often, and are defined with the following format:

function name {
commands
}

To maintain compatibility with the Bourne shell, functions can also be declared with this POSIX-style format:
function-name() {
commands
}

These types of functions have many limitations compared to Korn shell style functions, such as no support for local variables.

### 20.3 Scope & Availability

By default, functions are not available to subshells. This means that a regular function that was read in your working environment, .profile file, or environment file would not be available in a Korn shell script.

To export a function, use the typeset -fx command:
typeset -fx function-name

To make a function available across separate invocations of the Korn shell, include the  typeset -fx function-name command in the environment file.

### 20.4 Function Variables

All function variables, except those explicitly declared locally within the function with the typeset command, are inherited and shared by the calling Korn shell script. In this example, the X, Y, and Z variables are set within and outside of the function f:

$cat ftest X=1 function f { Y=2 typeset Z=4 print "In function f, X=$X, Y=$Y, Z=$Z"
X=3
}
f
print "Outside function f, X=$X, Y=$Y, Z=$Z" Notice that when executed, all the variable values are shared between the function and calling script, except for variable Z, because it is explicitly set to a local function variable using the typeset command. The value is not passed back to the calling Korn shell script:$ ftest
In function f, X=1, Y=2, Z=4
Outside function f, X=3, Y=2, Z=

The current working directory, aliases, functions, traps, and open files from the invoking script or current environment are also shared with functions.

### 20.5 Displaying Current Functions

The list of currently available functions are displayed using the typeset -f command.

To improve performance, functions can be specified to autoload. This causes the function to be read in when invoked, instead of each time a Korn shell script is invoked, and is used with functions that are not invoked frequently. To define an autoloading function, use the typeset -fu function-name command. Here, lsf is made an autoloading function:

### 20.10 Traps

The trap command is used to execute commands when the specified signals are received.
trap commands signals

Trap commands are useful in controlling side effects from Korn shell scripts. For example, if you have a script that creates a number of temporary files, and you hit the <BREAK> or <DELETE> key in the middle of execution, you may inadvertently leave the temporary files. By setting a trap command, the temporary files can be cleaned up on an error or interrupt.

The trap_test script creates some files, then removes them when an interrupt is received. Notice that the trap command is surrounded in single quotes. This is so that the FILES variable is evaluated when the signal is received, not when the trap is set.
$cat trap_test trap 'print "$0 interrupted - removing temp files" ;/
rm —rf $FILES; exit 1' 1 2 FILES="a b c d e f" touch$FILES
sleep 100
[2] 241
$read —p DATE$ print $DATE Thu Jul 18 12:23:57 PST 1996 Co-processes can be used to edit a file from within a Korn shell script. THE END ### Korn Shell Notes(IV) ## 16 The Environment ### 16.1 CDPATH The CDPATH variable is provided to make directory navigation easier. It contains a list of colon-separated directories to check when a full pathname is not given to the cd command. Each directory in CDPATH is searched from left-to-right for a directory that matches the cd argument. A : alone in CDPATH stands for the current directory. ### 16.2 PATH The PATH variable contains a list of colon-separated directories to check when a command is invoked. Each directory in PATH is searched from left-to-right for a file whose name matches the command name. If not found, an error message is displayed. A : alone in PATH specifies to check the current directory. ### 16.3 TMOUT The TMOUT variable specifies the number of seconds that the Korn shell will wait for input before displaying a 60-second warning message and exiting. If not set, the default used is 0, which disables the timeout feature. To set a 10-minute timer, set TMOUT to 600:$ TMOUT=600
This variable is usually set by the system administrator in the /etc/profile file.

### 16.4 MAILCHECK

The
MAILCHECK variable specifies how often, in seconds, to check for new
mail. If not set, or set to zero, new mail is checked before each new
prompt is displayed. Otherwise, the default setting is 600 seconds (10
minutes).

### 16.5 MAIL

The MAIL variable contains the name of a single mailbox file to check for new mail. It is not used if MAILPATH is set.

### 16.6 MAILPATH

The
MAILPATH variable contains a colon-separated list of mailbox files to
check for new mail and is used if you want to read multiple mailboxes.
It overrides the MAIL variable if both are set. This MAILPATH setting
specifies to check two mailbox files, /home/anatole/mbox and /news/mbox.
$print$MAILPATH

MAILPATH=/home/anatole/mbox:/news/mbox

Just
so you don't think you can go snooping around someone else's mailbox,
this only works if you have read permission on the mailbox file.
If MAILPATH is not set, there is no default.

### 16.7 TERM

The
TERM variable specifies your terminal type, and is usually set by your
system administrator in the global /etc/profile file. If it's not set
there, then it's probably in your ~/.profile file.

### 16.8 Enabling/Disabling Options

Korn shell options are enabled with the set -ooption or set -option command. For example, the noglob option disables file name substitution and can be set using either of these commands :
$set —f or$ set —o noglob
Options can also be enabled by specifying them on the ksh command line.
Here, a Korn subshell is started with the emacs option enabled:
$ksh —o emacs Options can be disabled with the set +o option or set +option command. In this example, the noglob option is disabled:$ set +o noglob

### 16.9 Displaying the Current Settings

The setting of the current options is displayed with the set -o command.

### 16.10 Aliases

Aliases
are command name macros used as shorthand for other commands,
especially frequently used ones. This saves a lot of typing time.
Aliases are defined with the alias name=value
command.Make sure to
enclose the value in quotes if it contains whitespace. Here we create
an alias l that is set to the ls -Fac command:
$alias l="ls —Fac" Now when you type in l, ls -Fac is executed:$ l

./

../

compress.Z*

func.Z*

test/

uncompress.Z*
. . .

Alias values can contain any text, including special characters, like wild-cards, pipes, or I/O redirection operators.

Here we set two aliases: p and h. When invoked, we get h instead of Hello.
$alias p='print' h=Hello$ p h

h
After the p alias is reset with a trailing blank, h gets substituted in the next command correctly:
$alias p='print ' h=Hello$ p h

Hello

#### 16.10.1 Displaying Current Aliases

A list of the current aliases is displayed using the alias command without arguments.

#### 16.10.2 Removing Aliases

Aliases are removed with the unalias command. Let's try it with the l alias:
$unalias l ## 17 Korn Shell Scripts ### 17.1 Positional Parameters Positional parameters are special variables used to keep track of arguments to the Korn shell, scripts, and functions. Positional parameter names contain only digits and cannot be set directly using variable=value syntax. By default, parameter zero (or$0) is set to the name of the shell, script or function.
$print$0

/bin/ksh
The remaining parameters 1 to n are set to each of the arguments passed
to the shell, script or function. For example, if you invoke a Korn
shell script called ptest and pass the arguments A, B, and C, then in the script ptest, $0 would be set to ptest,$1 to A, $2 to B, and$3 to C.

There are three special Korn shell variables that provide information about the current positional parameters. The first is $#, and it contains the number of positional parameters. The other two are$@ and $*, and they both contain all the positional parameters. So in the above ptest example,$# would be 3, and both $* and$@ would
be A B C. Here is a Korn shell script that manipulates positional
parameters. It displays the name of the current script, the number of
positional parameters, and the value of each of the positional
parameters:
$cat check_params print "Script name:$0"

print "Number of args passed: $#" print "Arguments passed:$*"

print "Arg 1=$1, Arg 2=$2, Arg 3=$3" ### 17.2 Modifying Positional Parameters By default,$0 is set to the name of the shell, script or function. It cannot be set or modified. The remaining parameters from $1 to$n can be reassigned with the shift
command. The shift command, with no arguments, shifts positional
parameters left once, so that $1 takes the value of$2, $2 takes the value of$3, and so on. The original value of $1 is lost. Let's change the check_params script so that it shifts the positional parameters left once:$ cat check_params

print "Script name: $0" print "Number of args passed:$#"

print "Arguments passed: $*" print "Arg 1=$1, Arg 2=$2, Arg 3=$3"

shift

print "Number of remaining args: $#" print "Remaining args:$*"

print "Arg 1=$1, Arg 2=$2, Arg 3=$3" When we run it again with the arguments A B:$ check_params A B

Script name: check_params

Number of args passed: 2

Arguments passed: A B

Arg 1=A, Arg 2=B, Arg 3=

Number of remaining args: 1

Remaining args: B

Arg 1=B, Arg 2=, Arg 3=
After the shift command, $1 is set to B and$2 is unset. The original value of $1 is lost. The positional parameters can be shifted left more than once by providing an integer argument to the shift command: shift n. ### 17.3 The exit command The exit command allows you to terminate execution from anywhere in a Korn shell script and return an exit value using this format: exit or exit n where n is the exit status to return. If n is not specified, the exit status of the previous command is used. If you don't use exit, then scripts finish after the last command is executed. ### 17.4 The [[...]] Command The [[...]] command is used to evaluate conditional expressions with file attributes, strings, integers, and more. The basic format is: [[ expression ]] where expression is the condition you are evaluating. There must be whitespace after the opening brackets, and before the closing brackets. Whitespace must also separate the expression arguments and operators. For example, these are incorrect: [[$X=$Y]] [[$X = $Y]] while this is correct: [[$X == $Y ]] Notice that there is white space between$X, $Y, and the = operator. If the expression evaluates to true, then a zero exit status is returned, otherwise the expression evaluates to false and a non-zero exit status is returned. If you are familiar with the test and [...] commands, then you'll recognize that [[...]] is just a new and improved version of the same commands. It basically functions the same way, except that a number of new operators are available. #### 17.4.1 Checking Strings We could use the [[...]] command to check if a variable is set to a certain value. Here, variable X is assigned abc, then evaluated in this expression:$ X=abc

$[[$X = abc ]] && print "X is set to abc"

X is set to abc
Using the test and [...] commands, the same command could be written as:
test "$X" = abc && print "X is set to abc" or [ "$X" = abc ] && print "X is set to abc"

To check if a variable is set to null, the -z option can be used:
[[ —z $VAR ]] && print "VAR is set to null" or it could be compared to the null string like this: [[$VAR = "" ]] && "VAR is set to null"

#### 17.4.2 Checking Patterns

The Korn shell also lets you compare strings to patterns. We could check if X begins with a 'a' like this:
$X=abc$ [[ $X = a* ]] && print "$X matches a*"

abc matches a*

Using the +([09]) pattern, we could check if X is set to a number:
$X=123$ [[ $X = +([0—9]) ]] && print "$X is a number"

123 is a number

#### 17.4.3 Checking File Attributes

The most basic operation to perform on a file is to see if it exists, and that can be done using the -a operator.
$touch tmp$ [[ —a tmp ]] && print "File tmp exists"

File tmp exists

This only indicates that it exists, but not much else. It may be a
directory, or a symbolic link, but using this operator, that's all we
know. If we wanted more information, the -f or -d operators could tell
us if a file existed and was a regular file (-f) or if it was just a
directory (-d).

#### 17.4.4 Checking Integer Attributes

The [[...]] command provides a few integer operators that allow
integers to be compared. It is frequently used to check the number of
command-line arguments. This expression evaluates to true if there are
less than or equal to three positional parameters set:
[[ $# —le 3 ]] && print "3 or less args given" The ((...)) command offers the same arithmetic comparison operators as the [[...]] command, plus many others. Besides offering more arithmetic operators, the ((...)) command provides substantial performance improvements over the [[...]] and test commands. #### 17.4.5 The ! Operator The ! operator negates the result of any [[...]] expression when used like this: [[ ! expression ]] For example, to check if X is not equal to abc:$ X=xyz

$[[ !$X = abc ]] && print "$X not equals abc" xyz not equals abc There is one logical operator that can only be implemented with the ! operator. There is no [[...]] file operator that will evaluate to true on a zero-length file.$ >emptyfile

$[[ ! —s emptyfile ]] && print "emptyfile is empty" emptyfile is empty #### 17.4.6 Compound Expressions (1) && - The AND Operator The && operator is used with the [[...]] command to test if multiple expressions are true using this format: [[ expression1 && expression2 ]] This expression checks if the noglob and noclobber options are set: [[ —o noglob && —o noclobber ]] (2) || - The OR Operator The | | operator is used with the [[...]] command to test if expression1 OR expression2 are true using this format: [[ expression1 | | expression2 ]] #### 17.4.7 [ [...] ] vs test and [...] The [[...]] command is preferred to test and [...], since many of the errors associated with test and [...] do not occur. ## 18 Control Commands ### 18.1 The case command The case command provides multiple-branch capability. The syntax for the case command is: where value is compared to pattern1, pattern2, ... patternn. The same patterns used in file name substitution can also be used in case statements to match patterns. The new Korn shell pattern matching formats also allow multiple case patterns to be given like this: ### 18.2 The for Command The basic syntax for the for command is: for variable in word1 word2 . . . wordn do commands done File name substitution, command substitution, and variable substitution can also be used to generate a list of word arguments for the for command. The first line of the previous command could have been given as: for FILE in chap[1-3] or for FILE in$(ls chap[1-3])
or
CHAPS=$(ls chap[1-3]) for FILE in$CHAPS

The $* and$@ variables can be used to loop on command-line arguments like this:
for variable in $* do commands done The for command can also be used without the list of word arguments: for variable do commands done The commands are executed once for each positional parameter, and variable is set to each successive positional parameter. It is equivalent to: for variable in$@

do

commands

done

### 18.3 The if Command

The basic syntax of the if command is:
if command1
then

commands

elif command2

then
commands
else

commands
fi

### 18.6 Breaking Out of Loops

break command  causes an exit from a loop-type command, but not from the entire script.

The break command can also be used to exit from a nested loop using this format:
break n
where  n specifies the nth enclosing loop to exit from.
Here is a new version of the nloop script that breaks out of both loops if i equals 2 and j equals 0:
$cat nloop for i in 1 2 3 do for j in 0 5 do if ((i == 2 && j == 0)) then break 2 else print "$i$j" fi done done Now the output would be:$ nloop
10
15
If
break was used instead of break 2, then only the inner for loop would
have been terminated, and execution would have continued with i set to
3 in the outer loop, and j set to 0 in the inner loop.

### 18.7 The continue Command

The continue command causes execution to continue at the top of the current loop.

18.8 The select Command
The select command
is used to display a simple menu that contains numbered items, and a
prompt message. The syntax for the select command is:

select variable in word1 word2 . . . wordn
do

commands
done

where word1 through wordn are displayed as numbered menu choices followed by a prompt (default #?).

If the response is in the range 1 through n, then variable is set to the corresponding word, REPLY is set to the response, and the commands are executed. Execution continues until a break, exit, return, or EOF is encountered.

### 18.8 The select Command

The
select command is used to display a simple menu that contains numbered
items, and a prompt message. The syntax for the select command is:

select variable in word1 word2 . . . wordn

do

commands

done

where word1 through wordn are displayed as numbered menu choices followed by a prompt (default #?). If the response is in the range 1 through n, then variable is set to the corresponding word, REPLY is set to the response, and the commands are executed. Execution continues until a break, exit, return, or EOF is encountered.

The select command can also be used without the list of word arguments:

select variable

do

commands

done

It
functions the same way as the previous select syntax, except that the
positional parameters are displayed as numbered menu choices from 1 to
n, instead of the words from the word list. It is equivalent to:

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

Once the readonly attribute is set, a variable cannot be assigned another value. Here, we use it to set up a restricted PATH:

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

## 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:
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"
$((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 ### Korn Shell Notes(II) # Korn Shell Notes ## 1 Useful Cmds wc - display a count of lines, words and characters in a file. It can be used to count the numbers together with other commands, such as ls, who and so on. cut - cut out selected fields of each line of a file. The name of each unique user that is logged on is displayed using this command:$ who | cut —f1 —d' ' | sort —u

anatole

root

print is a Korn shell specialized command which is similar to echo.

nl - line numbering filter.

## 2 Process Execution

### 2.1 Conditional Execution

You can implement a simple if command by using the && and || operators together like this:
command1 && command2 || command3
If command1 returns true, then command2 is executed, which causes
command3 to not be executed. If command1 does not return true, then
command2 is not executed, which causes command3 to be executed.

### 2.2 Grouping Commands

Commands enclosed in {} are executed in current shell. If

$echo "This is file temp:" ; cat temp | nl This is file temp: 1 The rain in Spain 2 falls mainly on the plain then by using {}s, the output will be:$ { echo "This is file temp:"; cat temp ; } | nl
1 This is file temp:
2 The rain in Spain
3 falls mainly on the plain
There must be whitespace after the opening {, and commands within the {}'s must be terminated with a semi-colon.

Commands
enclosed in () are executed in a subshell. Subshells are generated
whenever you enclose commands in ()'s, perform command substitution,
for background processes, and for coprocesses.A subshell is a separate
copy of the parent shell, so variables, functions, and aliases from the
parent shell are available to the subshell. However, subshells cannot
change the value of parent shell variables, functions, or aliases.

## 3 Input/Output Redirection

### 3.1 Redirecting Standard Output

By using the > symbol, the standard output of a command can be redirected to a file, instead of your terminal.

You can also use the > command to create an empty file:
$> tmp$ ls —s tmp
0 tmp
This is equivalent to touch tmp.

Standard output can be appended to a file by using the >> redirect operator.

Standard output is closed with the >&- redirect operator:
$echo "This is going nowhere" >&-$

### 3.2 The noclobber Option

To
prevent redirecting output to an existing file, set the noclobber
option. By default, this feature is usually disabled, but can be
enabled with the set -o noclobber command:
$ls > file.out$ set —o noclobber

The >| operator is used to force overwriting of a file, even if the noclobber option is enabled.

### 3.3 Redirecting Standard Input

Standard input to a command is redirected from a file using the < operator.

### 3.4 Redirecting Standard Error

As
with standard output, standard error is by default directed to your
terminal, but it can be redirected using the standard error file
descriptor (2) and the > operator, e.g. 2>

### 3.5 More With File Descriptors

The >&n operator
causes output to be redirected to file descriptor n. This is used when
you want to direct output to a specific file descriptor.In the next
command, the standard error and output are sent to ls.out by specifying
multiple redirections on the same command line. First, >&2
causes standard output to be redirected to standard error. Then,
2>ls.out causes standard error (which is now standard output and
standard error) to be sent to ls.out:
$ls tmp t.out 2>ls.out 1>&2$ cat ls.out
t.out

If
the output of the last command was redirected to a file using the >
operator, then only the standard output would be redirected. The
standard error would still be displayed on your terminal.
${echo "This is going to stdout"} >&1;/ echo "This is going to stderr" >&2;} >out This is going to stderr$ cat out
This is going to stdout.

The n>&m operator
causes the output from file descriptors n and m to be merged. This
operator could be used in the previous command to direct both the
standard output and standard error to the same file.

If you wanted the standard output and standard error appended to the output file, the >> operator could be used.

### 3.6 Here Document

Here documents is a term used for redirecting multiple lines of
standard input to a command. In looser terms, they allow batch input to
be given to programs and are frequently used to execute interactive
commands from within Korn shell scripts. The format for a here document
is:
command << word
or
command <<-word
where lines that follow are used as standard input to command until word is read.

The
other variation, command <<- word, deletes leading tab characters
from the here document. It is often used over the first variation to
produce more readable code when used within larger scripts. A good use
for here documents is to automate ftp file transfers. This snippet of
code could be used within a larger script to automatically ftp code to
or from another server.

The /dev/null file is like the system trash bin. Anything redirected to it is discarded by the system.

## 4 File Name Substitution

### 4.1 The * Character

The
* matches any zero or more characters in current directory, except
those begin with the "." character. These must be explicitly matched.

### 4.2 The ? Character

The ? character matches exactly one character.

### 4.3 The [] Character

The [] characters match a single, multiple, or range of characters.
This command lists file names beginning with d or m, and ending with any number 1 through 5:

In
the range argument, the first character must be alphabetically less
than the last character. This means that [c-a] is an invalid range.
This also means that pattern [0-z] matches any alphabetic or
alphanumeric character, [A-z] matches any alphabetic character (upper
and lower case), [0Z] matches any alphanumeric or upper case
alphabetic character, and [09] matches any alphanumeric character.

Multiple ranges can also be given. The pattern [a-jlmr3-7] would match files names beginning with the letters a through j, l, m, r, and 3 through 7.

### 4.4 The ! Character

The ! character can be used with [ ] to reverse the match. In other words, [!a] matches any character, except a.
If we want to list all of the file names except those started with d, we could do this:

or it can be done more easily using [!d]:

Multiple and range arguments can also be negated. The pattern [!lro]* would match strings not beginning with l, r, or o, *[!25] would match strings not ending with 2 through 5, and *.[!Z] would match strings not ending in .Z.

### 4.5 Complex Patterns

Korn Shell also provides entire patterns matching.

#### 4.5.1 *(pattern)

This format matches any zero or more occurrences of pattern.

#### 4.5.5 !(pattern)

This format matches anything except pattern. To match any string that does not end in .c, .Z, or .o:
!(*.c|*.Z|*.o)
or any string that does not contain digits:
!(*[0-9]*)

### 4.6 Disabling File Name Substitution

File name substitution can be disabled by setting the noglob option using the set command:
$set —o noglob or$ set —f

The -o noglob and -f options
for the set command are the same. Once file name substitution is
disabled, pattern-matching characters like *, ?, and ] lose their
special meaning:
$ls a* a* not found$ ls b?
Within [...] patterns, a / character is used to remove the meaning of the special pattern-matching characters. This means that the [/*/?]* pattern would match file names beginning with * or ?.

## 5 Command Substitution

Command
substitution is a feature that allows output to be expanded from a
command. It can be used to assign the output of a command to a
variable, or to imbed the output of a command within another command.
The format for command substitution is:
$(command) where command is executed and the output is substituted for the entire$(command) construct.
For example, to print the current date in a friendly format:
$echo The date is$(date)
The date is Fri Jul 27 10:41:21 PST 1996

### 5.1 Bourne Shell Compatibility

For compatibility with the Bourne shell, the following format for command substitution can also be used:
command 
Using . . . command substitution, we could get the names of the files in the current directory like this:
$echo ls are in this directory NEWS asp bin pc are this directory ### 5.2 Directing File Input There is also a special form of the$(...) command that is used to substitute the contents of a file. The format for file input substitution is:
$(<file) This is equivalent to$(cat file) or cat file`, except that it is faster, because an extra process does not have to be created to execute the cat command.

### 5.3 Arithmetic Operations

Another form of the $(...) command is used to substitute the output of arithmetic expressions. The value of an arithmetic expression is returned when enclosed in double parentheses and preceded with a dollar sign.$((arithmetic-expression))
Here are a few examples.
$echo$((3+5))

8

$echo$((8192*16384%23))

9

### 5.4 Tilde Substitution

Tilde substitution is used to substitute the pathname of a user's home
directory for ~user. Words in the command line that start with the
tilde character cause the Korn shell to check the rest of the word up
to a slash. If the tilde character is found alone or is only followed
by a slash, it is replaced with the value of the HOME variable.

# Korn Shell Notes

### 1 Useful Cmds

wc - display a count of lines, words and characters in a file.
It can be used to count the numbers together with other commands, such as ls, who and so on.

cut - cut out selected fields of each line of a file.
The name of each unique user that is logged on is displayed using this command:
$who | cut —f1 —d' ' | sort —u anatole root print is a Korn shell specialized command which is similar to echo. nl - line numbering filter. ### 2 Conditional Execution You can implement a simple if command by using the && and || operators together like this: command1 && command2 || command3 If command1 returns true, then command2 is executed, which causes command3 to not be executed. If command1 does not return true, then command2 is not executed, which causes command3 to be executed. ### 3 Grouping Commands Commands enclosed in {} are executed in current shell. If$ echo "This is file temp:" ; cat temp | nl
This is file temp:
1 The rain in Spain
2 falls mainly on the plain
then by using {}s, the output will be:
${ echo "This is file temp:"; cat temp ; } | nl 1 This is file temp: 2 The rain in Spain 3 falls mainly on the plain There must be whitespace after the opening {, and commands within the {}'s must be terminated with a semi-colon. Commands enclosed in () are executed in a subshell. Subshells are generated whenever you enclose commands in ()'s, perform command substitution, for background processes, and for coprocesses.A subshell is a separate copy of the parent shell, so variables, functions, and aliases from the parent shell are available to the subshell. However, subshells cannot change the value of parent shell variables, functions, or aliases. ### 4 Redirecting Standard Output By using the > symbol, the standard output of a command can be redirected to a file, instead of your terminal. You can also use the > command to create an empty file:$ > tmp
$ls —s tmp 0 tmp This is equivalent to touch tmp. Standard output can be appended to a file by using the >> redirect operator. Standard output is closed with the >&- redirect operator:$ echo "This is going nowhere" >&-
\$