Perl Notes(I)

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
$sub = /&mysub; # reference to a named subroutine


            
          

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

一下代码可以根据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"等等。
传出值,是一个hostent的结构(如下)。如果函数调用失败,将返回NULL。

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) :
这个函数,是将类型为af的网络地址结构src,转换成主机序的字符串形式,存放在长度为cnt的字符串中。
这个函数,其实就是返回指向dst的一个指针。如果函数调用错误,返回值是NULL。

编译时要加上-lsocket选项,否则编译器将会报出invalid reference的错误。如: gcc -o name2addr name2addr.c -lsocket.

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* 

此时可以理解为x指向一个ulong类型的数组 
[-1] : 表示去x前面的那个元素 

上面的代码等价与 

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

一般情况下不会用 下表-1,估计此处有什么特殊用法,要看实际是怎么用的了.


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

ulong getcallerpc(void *x) 

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

在((ulong*)(x))[-1] 中: 
x是一个指针 
(ulong*)(x):将x转换为ulong型的指针,我们假设(ulong*)(x)转换后指针为y,则 
((ulong*)(x))[-1]为:y[-1],而y[-1]就指向y首地址前面的那个地址。这种情况只有 
当你自己知道前面那个地址是什么了,也就是楼上所说的特殊用法了。~_~

NULL Pointer Bugs

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

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

where 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:
        ${!variable[subscript]}
For example, all and a specific exchange rate is displayed here:
    $ print ${!exchange_rate[*]}
    0.15 1.7
    $ print "The DM exchange rate is:${exchange_rate[DM]}"
    1.7


10 Compound Variables

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


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


11 Quoting

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


11.1 Single Quotes

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

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

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


11.2 Double Quotes

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

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

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

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


11.3 Back Quotes

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


12 Command History File

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

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

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


13 The fc Command

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

13.1 Displaying the Command History File

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

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


13.2 Editing the Command History File

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

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

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


14 Job Control

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

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

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

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

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


14.2 Checking Job Status

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

Stopped or background jobs are terminated with the kill command.

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


14.3 Job Control

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


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

14.4 Job Names

15 Performing Arithmetic

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



15.1 The let Command

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

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

15.2 The ((...)) Command

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



15.3 Declaring Integer Variables

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

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


15.4 Arithmetic Constants

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

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


15.5 Random Numbers

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

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


16 The Environment

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

3.7 Discarding Standard Output

  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.

This pattern matches anti, antic, antigen, and antique: $ match anti*(c|gen|que)

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.

4.5.4 @(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" >&-
    $

行行出状元——表扬683路公交车售票员wen师傅

今天坐683路公交车,又遇到了一个月前遇到的那位售票员(http://blog.csdn.net/bonny95/archive/2008/10/12/3062688.aspx)。她依然是那样热情的帮助乘客,依然如数家珍的报站名,依然用音乐抚慰着乘客拥挤的心灵。

不同的是:车厢内更加整洁了;车厢后面多了一排小花;车厢内的高台上(新型公交车有比较大的高台)铺着她自己做的小垫子供人坐,合理利用了空间,也为乘客提供了方便;大多数乘客已经习惯了她的热诚,放心的把东西交给她保管,甚至有些乘客已经成了她的朋友(亲眼见到一位小姐亲切的叫她“wen姐”和她打招呼,不知道是“闻”还是“文”);绝大多数公交车内一片漆黑(晚上),只有她的车内灯火通明。

另外,一位中年妇女下车时不小心把买的爆米花弄撒了,wen师傅连忙安慰她。由此令我联想到坐某辆公交车,由于司机急刹车致使某位小姑娘摔倒在地,小姑娘的同伴抱怨时,而那位售票员竟然还大声呵斥摔倒的小姑娘为什么不小心……

到了某个我家附近不出名的小站,wen师傅一口气将周围所有的饭店统统报了出来。我不禁伸出大拇指称赞,她笑着说“其实我只是比较喜欢吃东西”我抓住机会看了看她的工作牌,只看清了“120513C”,不知道是不是她的工号。

我要由衷的谢谢她——她用实际行动告诉了我们无论什么事情,哪怕别人都认为没有前途或者无可改进,只要用心,照样也可以做的风生水起。