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地址:
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.
看到一个函数,定义如下:
((ulong*)(x)) 将void* 的x针针强制转换为 ulong*
此时可以理解为x指向一个ulong类型的数组
[-1] : 表示去x前面的那个元素
上面的代码等价与
ulong px=(ulong*)x
--px
return (*px)
一般情况下不会用 下表-1,估计此处有什么特殊用法,要看实际是怎么用的了.
在((ulong*)(x))[-1] 中:
x是一个指针
(ulong*)(x):将x转换为ulong型的指针,我们假设(ulong*)(x)转换后指针为y,则
((ulong*)(x))[-1]为:y[-1],而y[-1]就指向y首地址前面的那个地址。这种情况只有
当你自己知道前面那个地址是什么了,也就是楼上所说的特殊用法了。~_~
19. Input/Output Commands
Here, file redir.out is opened as file descriptor 5 for reading and writing: This is going to fd 5 Standard input can be taken from a file like this:
19.1 Escape Characters
$ 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
$ 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
To finish up, we use another exec to close file descriptor 5:
$ exec 5<&—
exec 0<file
Commands could be read in from file, and it would be almost as if you typed them at your terminal.
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
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.
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
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
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
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.
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.
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.
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.
The list of currently available functions are displayed using the typeset -f command.
To improve performance, functions can be specified to autoload. This causes the function to be read in when invoked, instead of each time a Korn shell script is invoked, and is used with functions that are not invoked frequently. To define an autoloading function, use the typeset -fu function-name command. Here, lsf is made an autoloading function:
$ 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.
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 get, set, or unset. These correspond to the following operations on the variable:
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:
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.
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.
Functions are removed by using the unset -f command. Here, the rd function is removed:
$ unset -f rd
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.
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.
The trap command can also be used to reset traps to their default action by omitting the command argument:
trap - signals
or
trap signals
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 'commands' 0
or
trap 'commands' EXIT
This could be used to consolidate Korn shell script cleanup functions into one place.
If multiple traps are set, the order of precedence is:
The Korn shell traps KEYBD signals (sent when you type a character) and automatically assigns the following reserved variables:
The Korn shell provides a number of options that are useful in debugging scripts: noexec, verbose, 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.
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
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:20.12 Co-Processes
$ 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 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.
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.
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.
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).
The MAIL variable contains the name of a single mailbox file to check for new mail. It is not used if MAILPATH is set.
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.
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.
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
The setting of the current options is displayed with the set -o command.
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
A list of the current aliases is displayed using the alias command without arguments.
Aliases are removed with the unalias command. Let's try it with the l alias:
$ unalias l
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"
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.
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.
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.
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 +([09]) 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
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).
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.
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
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 ]]
The [[...]] command is preferred to test and [...], since many of the errors associated with test and [...] do not occur.
The case command provides multiple-branch capability. The syntax for the case command is:
The The basic syntax for the for command is: File name substitution, command substitution, and variable substitution
where value is compared to pattern1, pattern2, ... patternn.
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
for variable in word1 word2 . . . wordn
do
commands
done
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
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
The basic syntax of the if command is:
if command1
then
commands
elif command2
then
commands
else
commands
fi
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.
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.
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
6 Variables
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: 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: 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. 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:
$ X=6.1 Variable Attributes
typeset-attribute variable=value
or
typeset-attribute variable6.2 Lowercase (-l) and Uppercase (-u) Attributes
$ typeset —l MYSYS=ASPD
Despite the fact that MYSYS was assigned uppercase ASPD, when accessed, the value is displayed in lowercase:
$ print $MYSYS
aspd
$ typeset —u MYSYS
$ print $MYSYS
ASPD
Once the readonly attribute is set, a variable cannot be assigned another value. Here, we use it to set up a restricted PATH:
$ 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.
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
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.
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 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
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
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.
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.
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.
A 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
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.
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.
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
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.
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.
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.
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.
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}
$
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}
$
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.
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
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
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
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.
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
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.
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.
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.
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.
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 . . .
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
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]
. . .
[datatype] fieldn[=value]
)
The syntax to display the value of a compound variable field is:
${compound_variable.field}
There are three types of quotes: single quotes, double 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.
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.
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
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
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.
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.
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.
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
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.
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.
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
All of the operators from the C programming language (except ++, --, and ?:) are now supported by the Korn shell.
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.
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))
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"
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
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.
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.
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.
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.
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" >&-
$
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.
Standard input to a command is redirected from a file using the < operator.
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>
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.
Here documents is a term used for redirecting multiple lines of
standard input to a command. In looser terms, they allow batch input to
be given to programs and are frequently used to execute interactive
commands from within Korn shell scripts. The format for a here document
is:
command << word
or
command <<-word
where lines that follow are used as standard input to command until word is read.
The
other variation, command <<- word, deletes leading tab characters
from the here document. It is often used over the first variation to
produce more readable code when used within larger scripts. A good use
for here documents is to automate ftp file transfers. This snippet of
code could be used within a larger script to automatically ftp code to
or from another server.
The /dev/null file is like the system trash bin. Anything redirected to it is discarded by the system.
The
* matches any zero or more characters in current directory, except
those begin with the "." character. These must be explicitly matched.
The ? character matches exactly one 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), [0Z] matches any alphanumeric or upper case
alphabetic character, and [09] 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.
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, *[!25] would match strings not ending with 2 through 5, and *.[!Z] would match strings not ending in .Z.
This pattern matches anti, antic, antigen, and antique: $ match anti*(c|gen|que)
This format matches any zero or one occurrences of pattern. Here are some more patterns using this format:
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)*
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]*)
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 ?.
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
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
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.
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
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.
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.
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.
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.
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路公交车,又遇到了一个月前遇到的那位售票员(http://blog.csdn.net/bonny95/archive/2008/10/12/3062688.aspx)。她依然是那样热情的帮助乘客,依然如数家珍的报站名,依然用音乐抚慰着乘客拥挤的心灵。
不同的是:车厢内更加整洁了;车厢后面多了一排小花;车厢内的高台上(新型公交车有比较大的高台)铺着她自己做的小垫子供人坐,合理利用了空间,也为乘客提供了方便;大多数乘客已经习惯了她的热诚,放心的把东西交给她保管,甚至有些乘客已经成了她的朋友(亲眼见到一位小姐亲切的叫她“wen姐”和她打招呼,不知道是“闻”还是“文”);绝大多数公交车内一片漆黑(晚上),只有她的车内灯火通明。
另外,一位中年妇女下车时不小心把买的爆米花弄撒了,wen师傅连忙安慰她。由此令我联想到坐某辆公交车,由于司机急刹车致使某位小姑娘摔倒在地,小姑娘的同伴抱怨时,而那位售票员竟然还大声呵斥摔倒的小姑娘为什么不小心……
到了某个我家附近不出名的小站,wen师傅一口气将周围所有的饭店统统报了出来。我不禁伸出大拇指称赞,她笑着说“其实我只是比较喜欢吃东西”我抓住机会看了看她的工作牌,只看清了“120513C”,不知道是不是她的工号。
我要由衷的谢谢她——她用实际行动告诉了我们无论什么事情,哪怕别人都认为没有前途或者无可改进,只要用心,照样也可以做的风生水起。