### 由服务器名字(Host name)获得IP地址

1. #include <stdio.h>
2. #include <netdb.h>
3. #include <sys/socket.h>
4. #include <arpa/inet.h>
5. #include <netinet/in.h>
6. int main(int argc,char **argv)
7. {
8.     struct hostent *hptr;
9.     struct in_addr *in_addr_ptr;
10.     char *ptr,**pptr,**listptr,*addr_ptr;
11.     char str[32];
12.     /*Host name--the first param*/
13.     ptr=argv[1];
14.     if((hptr=gethostbyname(ptr))==NULL)
15.     {
16.         printf("gethostbyname error for host: %s/n",ptr);
17.         return -1;
18.     }
19.     /*print official host name*/
20.     printf("offial host name: %s/n",hptr->h_name);
21.     /*print all the aliases of the host*/
22.     for(pptr=hptr->h_aliases;*pptr!=NULL;pptr++)
23.         printf("alias:%s/n",*pptr);
24.     /*print IP address*/
25.     switch (hptr->h_addrtype) {
26.     case AF_INET:
27.         listptr = hptr->h_addr_list;
28.         if ( (in_addr_ptr = (struct in_addr *) *listptr) != NULL) {
29.             addr_ptr = inet_ntoa(*in_addr_ptr);
30.
31.             printf("address: %s/n",addr_ptr);
32.
33.             return(0);
34.         }
35.         else {
36.             return(NULL);
37.         }
38.     default:
39.         printf("unknown address type %d/n",hptr->h_addrtype);
40.         return(NULL);
41.     }
42.     return 0;
43. }

struct hostent *gethostbyname(const char *name);

www.google.com","wpc"等等。

struct hostent {
char  *h_name;
char  **h_aliases;
int   h_addrtype;
int   h_length;
char  **h_addr_list;
};

char *h_name 表示的是主机的规范名。例如
www.google.com的规范名其实是www.l.google.com
char   **h_aliases 表示的是主机的别名。
www.google.com就是google他自己的别名。有的时候，有的主机可能有好几个别名，这些，其实都是为了易于用户记忆而为自己的网站多取的名字。
int   h_addrtype 表示的是主机ip地址的类型，到底是ipv4(AF_INET)，还是ipv6(AF_INET6)
int   h_length 表示的是主机ip地址的长度
int   **h_addr_lisst 表示的是主机的ip地址，注意，这个是以网络字节序存储的。千万不要直接用printf带%s参数来打这个东西，会有问题的哇。所以到真正需要打印出这个IP的话，需要调用inet_ntop()。

#include <arpa/inet.h>

const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) ：

### return (((ulong*)(x))[-1])

1. #include "u.h"
2. #include "lib.h"
3. ulong
4. getcallerpc(void *x)
5. {
6.     return (((ulong*)(x))[-1]);
7. }

((ulong*)(x))  将void* 的x针针强制转换为 ulong*

[-1] : 表示去x前面的那个元素

ulong px=（ulong*）x
--px
return (*px)

------------------------------------------------------------------------

ulong getcallerpc(void *x)

return (((ulong*)(x))[-1]);

x是一个指针
（ulong*)(x)：将x转换为ulong型的指针，我们假设（ulong*)(x)转换后指针为y，则
((ulong*)(x))[-1]为：y[-1]，而y[-1]就指向y首地址前面的那个地址。这种情况只有

# NULL Pointer Bugs

A NULL character pointer is NOT the same as a pointer to a NULL string. In Solaris, the following program will lead to a "Segmentation Fault".

1. #include <stdio.h>
2. #include <string.h>
3. int main()
4. {
5.     char *string=NULL;
6.     printf("/n String length=%d",strlen(string));
7.     return 0;
8. }

I don't know hwy this happens clearly now, and it should be pay more attention.

### Korn Shell Notes(V)

19. Input/Output Commands

### 19.1 Escape Characters

The /c escape character causes the trailing newline to be dropped from the output. It is often used to create prompts.
$print "Enter choice: /c" Enter choice:$
Notice that the command prompt was displayed following the argument, and not on the next line.

### 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 Here is ANSWER:$ print $ANSWER ANYTHING ### 19.4.4 The REPLY variable 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. ### 20.6 Autoloading Functions 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:$ typeset —fu lsf

The autoload alias can also be used to define an autoloading function. On most systems, it is preset to typeset -fu.

The FPATH variable which contains the pathnames to search for autoloading functions must be set and have at least one directory for autoloading functions to work.

### 20.7 Discipline Functions

Discipline functions are a special type of function used to manipulate variables. They are defined but not specifically called. Rather, they are called whenever the variable associated with the function is accessed.

There are some specific rules as to how discipline functions are named and accessed. First of all, discipline functions are named using this syntax:
name.function

Notice the the funcion has two parts separated with a dot. The first part name corresponds to the name of a variable, and the second part must be getset, or unset. These correspond to the following operations on the variable:

• get     whenever the base discipline variable is accessed
• set     whenever the base discipline variable is set
• unset     whenever the base discipline variable is unset

For example, the discipline function LBIN.get, LBIN.set, LBIN.unset is called whenever the variable LBIN is accessed, set, or unset.

All three discipline functions are optional, so not all need to be specified. Within a discipline function, the following special reserved variables can be used:

• .sh.name     name of current variable
• .sh.value     value of the current variable
• .sh.subscript     name of the subscript (if array variable)

From a practical perspective, discipline functions are often used to help debug by tracing the setting and current value of variables in running scripts. Here is a function that can be used to trace setting the value of X:
function X.set {
print "DEBUG: ${.sh.name} =${.sh.value}"
}

Discipline functions are also a good place to centralize your variable assignment validation rules. Here is a function that checks to make sure that X it set ao a number between 3 and 10:
function X.set {
if (( .sh.value<3 || .sh.value >10 ))
then
print "Bad value for ${.sh.name}:${.sh.value}"
fi
}

Note that builtin functions can also be used as additional discipline functions.

### 20.8 FPATH

The FPATH variable contains a list of colon-separated directories to check when an autoloading function is invoked. It is analogous to PATH and CDPATH, except that the Korn shell checks for function files, instead of commands or directories. Each directory in FPATH is searched from left-to-right for a file whose name matches the name of the function. Once found, it is read in and executed in the current environment. With the following FPATH setting, if an autoloading function lsf was invoked, the Korn shell would check for a file called lsf in /home/anatole/.fdir, then /etc/.functions, and if existent, read and execute it:

$print$FPATH
/home/anatole/.fdir:/etc/.functions

There is no default value for FPATH, so if not specifically set, this feature is not enabled.

### 20.9 Removing Function Definitions

Functions are removed by using the unset -f command. Here, the rd function is removed:
$unset -f rd ### 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$ trap_test
Ctl-c
trap_test interrupted - removing temp files

If an invalid trap is set, an error is generated.

#### 20.10.1 Ignoring Signals

The trap command can be used to ignore signals by specifying null as the command argument:
trap  ""  signals
This could be used to make all or part of a Korn shell script uninterruptable using normal interrupt keys like Ctl-c.

#### 20.10.2 Resetting Traps

The trap command can also be used to reset traps to their default action by omitting the command argument:
trap - signals
or
trap signals

#### 20.10.3 Exit & Function Traps

A trap can be set to execute when a Korn shell script exits. This is done by using a 0 or EXIT as the signals argument to the trap command:
trap 'commands0
or
trap '
commandsEXIT
This could be used to consolidate Korn shell script cleanup functions into one place.

#### 20.10.4 Trap Signal Precedence

If multiple traps are set, the order of precedence is:

• DEBUG
• ERR
• Signal Number
• EXIT

#### 20.10.5 Trapping Keyboard Signals

The Korn shell traps KEYBD signals (sent when you type a character) and automatically assigns the following reserved variables:

• .sh.edchar     contains last character of key sequence
• .sh.edtext     contains current input line
• .sh.edmode     contains NULL character (or escape character is user in command mode)
• .sh.edcol     contains position within the current line

### 20.11 Debugging Korn Shell Scripts

The Korn shell provides a number of options that are useful in debugging scripts: noexecverbose, and xtrace. The noexec option causes commands to be read without being executed. It is used to check for syntax errors in Korn shell scripts. The verbose option causes the input to be displayed as it is read. The xtrace option causes the commands in a script to be displayed as they are executed.

#### 20.11.1 Debugging with trap

The trap command can also be helpful in debugging Korn shell scripts. The syntax for this type of trap command is:
trap commands DEBUG
or
trap commands ERR

### 20.12 Co-Processes

Co-processes are commands that are terminated with a |& character. They are executed in the background, but have their standard input and output attached to the current shell. The print -p command is used to write to the standard input of a co-process, while read -p is used to read from the standard output of a co-process. Here, the output of the date command is read into the DATE variable using the read -p command:
$date |& [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

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

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

$[[ —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.4 The while Command ### while command1 do commands done ### 18.5 The until Command ### The until command is another looping command. It's like the while command, except that instead of looping while the condition is true, it loops while the condition is false. The syntax for the until command is: until command1 do commands donewhere commands are executed until command1 returns a zero exit status. ### 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: select variable in "$@"

do

commands

done

### korn Shell Notes(III)

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:

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

# 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" >&-
$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 tmp not found 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

#### 4.5.2 ?(pattern)

This format matches any zero or one occurrences of pattern. Here are some more patterns using this format:

#### 4.5.3 +(pattern)

This format matches one or more occurrences of pattern.

This format matches exactly one occurrence of pattern. Let's look for words beginning with Ala or Cla:     $match @([AC]la)* #### 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? b? not found 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(K Shell) Notes (I) # 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" >&-$

## Part III Tcl Data Structures

### 1 More about Variables

• The set command

The set
command is used to define variables of any type. In addition, the set
command will return the value  of a variable if it is only passed a
single argument. It treats that argument as a variable name and returns
the current value of the variable.

In the last command, $name gets substituted with var. Then the set command returns the value of var, which is the value of var. Another way to achieve a level of indirection like this is with nested set commands. The last set command above can be written as follows: set [set name] => the value of var • The unset command You can delete a variable with the unset command: unset varName varName2 ... • Using info to find out about variables The existence of a variable can be tested with the info exists command. e.g. if ![info exists foobar]{ set foobar 0 } else { incr foobar } ### 2 Tcl Lists The Tcl list has the same structure as a Tcl command. That is, a list is simply a string with list elements separated by white space.Braces or quotes can be used to group words with whitespace into a single list element. ### 3 Constructing Lists: list, lappend and concat The list command constructs a list out of its arguments such that there is one list element for each argument. if any of the arguments contain special characters, the list command adds some quoting to ensure they are parsed as a single element of the resulting list. e.g. Constructing a list with the list command set x {1 2} => 1 2 set x => 1 2 list$x /$foo => {1 2} {$} foo
[Note]: The braces used to group the list value into one argument to the set command are not part of the list value.

The lappend command is used to append elements to the end of a list. You can call lappend with the name of an undefined variable and the variable will be created.
e.g.
lappend new 1 2
=> 1 2
lappend new 3 "4 5"
=> 1 2 3 {4 5}
set new
=> 1 2 3 {4 5}

The concat
command is useful for splicing together lists. It works by
concatenating its arguments together, separating them with spaces. This
multiple lists into one where the top-level list elements in each input
list are also top-level list elements in the resulting list.
e.g. Using concat to splice together lists.
concat 1 {2 3} {4 5 6}
=> 1 2 3 4 5 6
It turns out that double quotes behave much like the concat command.
e.g. Double quotes compared to the list command.
set x {1 2}
=> 1 2
set y "$x 3" => 1 2 3 set y [concat$x 3]
=> 1 2 3
set z [list $x 3] =>{1 2} 3 The basic rule is that list and lappend preserve preserve list structure, while concat(or double-quotes)eliminate one level of list structure. ### 4 Getting List Elements: llength, lindex, and lrange The llength command returns the number of elements in a list. The lindex command returns a particular element of a list. It takes an index. List indices count from zero. The keyword end means the last element, and it can be used with lindex, linsert, lrange and lreplace. e.g. lindex {1 2 3} 0 => 1 lindex {1 2 3} 2 => 3 The lrange command returns a range of list elements. It takes a list and two indices as arguments. e.g. lrange {1 2 3 {4 5}} 2 end => 3 {4 5} ### 5 Modifying Lists: linsert and lreplace The linsert command inserts elements into a list value at a specified index. If the index is 0 or less, then elements are added to the front. If the index is equal to or greater than the length of the list, then the elements are appended to the end. Otherwise, the elements are inserted before the element that is currentl as position index. lreplace is used to replace a range of list elements with new elements. If you don't specify any new elements, you effectively delete elements from a list. e.g. linsert {1 2} 0 new stuff => new stuff 1 2 set x [list a {b c} e d] => a {b c} e d lreplace$x 1 2 B C
=> a B C d
lreplace $x 0 0 => {b c} e d ### 6 Searching Lists: lsearch lsearch returns the index of a value in the list, or -1 if it is not present. lsearch supports pattern matching in its search. Glob-style pattern matching is default, and this canbe disabled with the -exact flag. The example below uses lreplace to delete elements by not specifying any replacement list elements. e.g. proc delete {list value} { set ix [lsearch -exact$list $value] if {$ix>=0} {
return [lreplace $list$ix $ix] } else { return$list
}
}

### 7 Sorting List: lsort

The three basic types of sorts are specified with the -ascii, -integer, or -real options. The -increasing or -decreasing option indicate the sirting order. The default option set is -ascii -increasing.

### 8 The split And join Commands

The split command
takes a string and turns it into a list by breaking it at specified
characters. Stray double-quotes or curly braces in the input can result
in invalid list structures and errors in your script. However, the
split command provides a robust way to turn input lines into proper Tcl
lists.

The
default split character is white space. If there are multiple separator
characters in a row, these result in empty list elements- the
separators are not collapsed. The following command splits on commas,
periods, spaces and tabs:

The join command
is the inverse of split. It takes a list value and reformats it with
specified characters separating the list elements. In doing so, it will
remove any curly braces from the string representation of the list that
are used to group the top-level elements.

### 9 Arrays

The index of an array is delimited by parentheses. The
index can have any string value, and it canbe the result of variable or
command substitution.
e.g.        set arra(index) value
The value of an array element is obtained with $substitution: e.g. set foo$arr(index)

If
you have complex indices, use a comma to separate different parts of
the index. Avoid putting a pace after the comma. It is legal, but a
space in an index value will cause problems because parenthesis are not
used as a grouping mechanism. The space in the index needs to be quoted
with a backslash, or hte whole variable reference needs to be grouped:
e.g.        set {arr(I'm asking for trouble)} {I told you so.}
If
the array index is stored in a variable, then there is no problem with
spaces in the variable's value. The following works fine:
e.g.
set index {
I'm asking for trouble}
set arr(\$index) {
I told you so.}
The
name of the array can be the result of a substitution. If the name of
the array is stored in another variable, then you must use set as shown
in the last command below to reference the array elements.

### 10 The Array Command

The array names command is perhaps the most useful because it allows easy iteration through an array with a foreach loop:
foreach index [array names arr] {command body}
The order of the names returned by array names is
arbitrary. It is essentially determined by the hash table
implementation of the array.
The array get and array set operations are used to convert between an array and a list. The list returned by array get
has an even number of elements.The first element is an index, and the
next is the corresponding array value. The ordering of the indexes is
arbitrary. The list argument to array set must have the same structure.

### 11 Environment Variables

In UNIX, the process environment variables are available through the global array env.
The name of the environment variable is the index,e.g. env(PATH), and
the array element contains the current value of the environment
variable.

### 12 Tracing Variable Values

The trace command lets you register a command to be called whenever a variable is accessed, modified or unset. The form is:
trace variable name ops command
The name is a Tcl variable name, which can be a simple
variable, an array or a element.If a whole array is traced, then the
trace is invoked when any element is used according to ops. The ops
argument is one or more of the letters: r for read traces, w for write
traces, and u for unset traces. The command is executed when one of
these events occurs. It is invoked as:
command name1 name2 op

Information about traces on a varible is returned with the vinfo option.
trace vinfo dynamic
=> {r FixDynamic}
A trace is deleted with the vdelete trace option, which has the same form as the varible option.