2.输出重新定向符
符号>与>>表示输出重新定向符。
在标准输出的情况下,如果原来的文件有内容,使用重新定向输出符>后,原有内容被新的内容所替代;若使用重新定向输出符>>,则新的内容将追加到原有内容的后面。
例如:
敲入命令行:
#date>file
表示把命令date的结果输出重新定向到文件file,并将文件file内原来的内容冲掉。
上面的两种定向输出,都是假定原有文件已经存在的情况。
如果定向符后面是一个新的文件名,那么Shell将建立这个文件。
例如:
>abc表示建立一个长度为零,名字为abc的文件
3.错误重新定向符
符号2>与2>>表示错误输出重新定向符。
执行unix系统命令时所产生的诊断输出,通常被定向到文件描述符2。
例如:
cctest.c2>>err
在这个命令行中,cc是C语言的编译命令,test.c是C语言编写的源程序。
2是标准错误输出的文件描述符。
用cc命令对test.c进行编译过程中出现的错误信息,通常放在标准错误输出文件中。
这个命令行,把标准错误输出文件重新定向到文件err。
其结果是把错误信息附加(appends)到了err文件的尾部,在使用重新定向符时应特别注意,文件描述符与重新定向符之间不能有空格或制表符,比如命令行:
2>>中的数字2与符号>>之间不留空格。
如果两个符号之间出现了空格或制表符,文件描述符就有可能被shell视为命令的一个参量。
8.1.1.6命令行和管道线
在unix系统中,可以若干命令连用,而每个命令之间由竖线“|”(称为管道符)隔开。
对于这样使用的命令序列,我们称它为管道线(pipeline)。
在管道线中,一个命令的输出(命令产生的结果),正是下一个命令的输入。
当然位于管道行的最后一个命令例外。
“过滤器”是在使用管道线时经常遇到的一个概念。
所谓“过滤器”是指管道线中的一个命令,过滤器首先读进输入,接着以某种方式将“输入”进行变换(相当于过滤),再将变换结果输出。
一个管道线通常由一系列过滤器组成。
Unix系统的过滤器有:
cuttrteepr
有关上述命令的使用,请参阅相关文档资料。
例如:
1.who|wc-1显示系统中注册的用户数。
2.who|grepbb显示在系统中注册,且用户名中包含字符串“bb”的用户。
3.who|grepbb|sort|pr
此行使用了三个管道符。
首先查出在系统中注册的用户清单;再从名单中找出名字中含有字符串“bb”的用户名;然后,把这些用户名按第一个字母顺序排列;最后,以页为单位把排列好的用户清单显示出来。
由此,可以看出“过滤器”在管道中的作用。
4.{date;who|wc-1;}>>log
这一行由三个命令组合使用。
把当前日期、在系统注册的用户数附加到log文件的尾部。
使用大括号时应当注意,在{的后面一定要有一个空格,而在}的前面要有一个分号“;”。
8.1.1.7命令替换
在shell中,可以把命令行中的命令由后引号(`…`)括起来。
对于一个由多参量组成的命令行,shell首先执行后引号中的命令,并且用这个命令的输出(执行这个命令产生的结果),来取代整个表达(即后引号及所包含的命令),这种在一个由若干命令组成的命令行中,由命令输出结果取代这个命令本身的表达方式,称为命令转换。
例1:
today=`date`后引号中的date命令的功能是,读出当前系统的时间和日
期。
然后,把执行date命令的结果赋给变量today。
进行命令转换时,后引号中可以是一个命令,也可以是多个命令的组合,比如管道线等。
例2:
users=`who|wc–l`表示将当前系统中注册低用户数,赋给了shell变量
users
例3:
用户wang敲入命令行:
$logmsg=`echoyourlogindirectoryis\`pwd\``
$echo$logmsg
回车后屏幕显示:
yourlogindirectoryis/usr/wang
8.1.2shell中的变量
在shell中,变量是一个字符串值的名字。
shell提供了定义变量的机制。
某些变量被作为位置参数用在命令行中;而另一些shell变量可由用户或shell给以赋值。
8.1.2.1位置参数
位置参数是shell变量的一种。
当一个shell过程被调用时,shell将隐含地建立位置参数。
在命令行上,位置0处是shell过程的命令名,其位置参数为$1、$2…$9。
Shell中规定,在调用一个shell时,它的参数最多不能超过9个。
如果参数多于9个,需要用shift命令进行读写操作。
8.1.2.2用户定义的变量
在shell中,用户可以自己定义变量。
变量名字可以字母组成,也可以由字母和数字混合组成。
如果是后者,一定要以字母开头。
赋值语句的格式为:
变量名=字符串
其中:
变量名是用户自己定义的变量名字
字符串作为一个值,赋给“变量名”所表示的变量。
注意:
1.在shell赋值语句中,等号的左右两侧都没有空格。
2.位置参数不能出现在赋值语句的左侧。
3.在一个赋值语句中可以有多个赋值,其赋值的顺序是从右到左。
例如:
MAIL=/usr/mail/wang
var=“echo$1$2$3$4”
stars=*****
asterisks=`$stars`
ABC=$stars
第一行,把一个文件的路径赋给变量MAIL。
第二行,双引号把字符串括起来,允许右侧空格、制表符或分号。
var的值是由字
符串“echo”和四个位置参数组成的字符串。
第三行,把字符串“*****”赋给变量stars。
第四行,变量asterisks的值是“$stars”,而不是“*****”。
第五行,变量ABC的值是“*****”。
8.1.2.3shell定义的变量(环境变量)
shell中的变量有两类:
一类是由用户设置的变量,它们被称为shell变量。
上一节的例子即是用户自己定义的shell变量,变量的名字可以任意确定,它的值也是根据需要设置的;另一类是由shell本身设置的变量,称之为环境变量。
它的名字是固定的,它们的值不是随意设置的。
比较可以看出,shell变量是在一个shell活动(如,shell程序运行)内部临时创建的变量,它被用来暂保存信息,当本次shell活动终止时,它就被丢弃了。
Shell变量只在shell程序内有效,对其它程序来说是不可见的。
所谓环境是对程序的运行而言的,在系统上运行的每一个程序,当它们投入运行时,在内存中都分配有一个专门的区域,这人区域被称为环境。
在一个程序运行时,它将继承其父进程(即调用本程序的那个程序,或者是本程序的主程序)的环境副本。
这时就要作用环境变量,把配置信息传递给子进程。
例如:
HOME表示用户注册主目录名
PATH表示shell寻找命令的路径
PSI用来作为屏幕提示的主字符串。
8.1.2.4预先定义的特殊变量
在shell中,下面几个变量具有特殊意义。
它们的设置,只能由shell进行,而不能通过用户进行重新设置。
$#记录传送给shell的参量数,但它不把shell过程自己的名字计数在内。
因
此,$#可以给出所设置的位置参数的个数。
$?
包含最后一个执行命令的返回结果。
它是一个十进制数字。
为零时,表示命
令执行成功。
$$这个变量表示当前进程的进程号。
因为对系统中现有的进程来说,进程号是
唯一的。
这个字符串常常被用来为临时文件产生唯一的文件名。
8.1.2.5shell说明
1.改变目录
cd命令的功能,是把当前目录改变为这个命令变量中指定的那个目录。
系统提供的这种手段,可以直接应用到shell程序中来。
2..profile文件
在用户每次向系统注册时,shell都要读该用户的.profile文件。
系统中的每个普通用户都有自己.profile文件。
超级用户在根下有一个.profile文件,通过它设置shell程序所需的环境变量。
3.运行标志
在shell中,通过set命令设置某些标志,可以使用户改变shell的功能。
其中标志项有:
-a标志变量,为export命令的使用,修改或建立标记。
-e如果shell是非交互式的,当一个命令以非零状态返回时将直接退出shell。
-f禁止文件名产生。
-h设置函数命令(即把函数当作命令使用)。
-k把全部的关键字参量放在命令的环境中。
-n读命令,但不执行这个命令。
-x:
命令执行时,这些命令和它们的参量同时显示在屏幕上。
但也有些shell命
令,比如用于循环体的“for”、“while”等并不显示。
-v:
读输入信息时,输入行在屏幕上显示。
对分析输入行的语法错误是非常有用
的。
例如:
#set-x
#echothisisatest
回车后,屏幕显示:
+echothisisatest
thisisatest
第一行:
echo命令和它的参量全部显示,行首的+号,提示用户检查是否有语句错
误。
第二行echo命令执行的结果。
注意:
在上述标志前使用加号“+”,表示关闭这个标志;使用减号“-”,表示设置这个标志。
8.1.3运行环境和流向控制
8.1.3.1命令运行的环境变量
在shell中,所有的变量及它们的值,都可以认为是命令开始执行时建立起来的运行环境。
此外,运行环境还包括这样一些变量,它们中一些是从父进程沿袭下来的变量,另一些是使用命令时,命令行上指定作为关键字参数的变量。
如果shell进程要给它的子进程传送变量,那么这个变量就必须使用export命令进行说明。
export命令也叫变量输出命令。
赋值形式为:
变量=值
例如:
TERM=vt100;exportTERM
8.1.3.2shell过程调用和参量传递
1.shell调用
shell实际上是一种命令。
我们可以按照unix系统提供命令的使用方法来使用它。
因此,调用shell有两种方法:
(1)shproc[arg]
它的含义是:
请示系统调用一个新的shell来读proc,方括号中的arg是proc运行所需的选项。
例如:
一个名字叫echo2的shell过程,其文本内容为:
forword
do
echo$word$word
done
在提示符下敲入命令行:
#shecho2abc
屏幕上将显示信息:
abcabc
或sh-vproc[arg]
其中,-v是执行标志,相当于在过程proc的开始处放了一个命令行:
set-v
例如上例给出的shell,在提示下符下敲入命令行:
#sh-vecho2abc
回车,屏幕显示:
forword
do
echo$word$word
done
abcabc
因此,使用了标志项-v后,它把shell过程的文本及执行这个过程所产生的结果全部显示在屏幕上。
同样,还可以设置其它标志项:
-x、-e、-u与-n。
(2)proc[arg]
如果proc是一个可执行文件,并且是一个不需编译就可执行的程序,这时,调用shell的方法可以为:
procargs
2.参量传给shell的过程
当一个命令行从键盘上敲入后,shell就对这个命令行进行扫描,并把形如$n的字符序列由第n个参量取代。
Shell过程的名字计数为$0。
这样的计数方法,就可以直接索引过程的名字,并且可以有9个位置参数。
多于9个位置参数的情况,可以用shift命令来处理。
shift命令如果不带任何参量,它的功能是把位置参量左移一位,即$1的值被移出,$2的值取代$1的值,$3的值取代$2的值,……依次类推。
由此可见,左移后,原来$1的值丢掉了,它不能移到$0的位置。
如果这个命令带有参量:
shiftn,此处n是一个数字,那么shift所完成的功能是:
每次把位置参数左移n位。
例如:
#file
whiletest$#!
=0
do
echo$*
shift
done
其中
第一行:
含有字符“#”,表示注释行。
第二行:
循环命令while用于检查判断,当参数的个数$#不为0时,继续执行循环
体中的命令。
如果使用下面命令调用程序file:
fileabcde
将会显示结果:
abcde
bcde
cde
de
e
结果表明,循环体被执行了5次。
从第二次开始,每执行一次,就把$1位置上的参量左移一位。
8.1.3.3shell流向控制
所谓流向控制,是指shell过程中的循环、检测、设陷、退出等涉及到shell过程运行走向的一系列操作。
相关的几个问题
(1)管道线
管道线是一个包含了一个或多个命令的序列。
命令之间由管道符“|”隔开。
在一个管道线中,前一个命令的标准输出都是与之相连的后一个命令的标准输入。
管道线中的每个命令是独立运行的,shell一直等到最后一个命令执行完成。
整个管道线的退出状态(即管道行完成时返回的状态),是管道行中最后一个进程的退出状态。
(2)命令清单
命令清单是由一个或多个管道线构成的序列。
管道线之间可以是符号“;”、“&”、“&&”、“||”。
命令清单可以由“;”或“&”来结束。
命令清单中如果两个管道线之间是用分号隔开的,将按管道线的前后顺序执行,也就是说,shell要等待一个管道线执行完毕才能读下一个管道线。
如果两个管道线之间是由“&”隔开的,那么前一个管道行异步地在后台执行。
例如:
nohupccprog.c&
其中cc是unix操作系统上所配的c语言的编译器。
prog.c是用c语言编写的源程序。
由于这个命令行用“&”结束,因此在编译器对源程序prog.c进行编译过程中,用户敲入中断键或键入quit命令退出系统,既不能中断、也不会退出编译的进行。
(3)nohup命令
其功能是运行一个命令,并且不受任何挂起(hangups)和退出的影响。
命令行格式:
nohupcommand[arguments]
其中:
command代表要运行的命令的名字
arguments表示参量。
注意:
使用这个命令时,如果用户没有对输出进行重新定向,那么,它将把输出结果存放到nohup.out文件中;如果用户在当前目录下,不具有写操作权限,那么nohup命令的输出就被重新定向到$HOME/nohup.out。
(4)符号&&和||
符号&使一些程序能在后台运行,究竟哪些程序可以在后台运行,要视情况而定。
因此,“&”的使用也受到一些限制。
特别是在系统负载比较重时,不宜启动过多的后台进程。
符号&&(and-if)与||(or-if)的作用是使管道线有条件地执行。
它们在命令行上操作的优先级是相同的,并且低于操作符&和|的优先权。
||的格式为:
cmd1||cmd2
其中cmd1、cmd2分别代表命令1和2。
命令行的意义是,先执行命令cmd1,并对这个命令执行后的返回状态进行检测。
只有在cmd1运行失败时(返回状态非零时认为运行失败,为零时表示运行成功)才执行命令cmd2。
操作符||在这个命令行中的作用是进行条件判断,相当于下列语句:
ifcmd1
test$?
!
=0
then
cmd2
fi
&&的格式:
cmd1&&cmd2
其中&&的作用是进行一个与||互补的检测。
其作用是:
只要第一个命令cmd1执行成功(返回状态为零),就执行第二个命令cmd2。
例如:
cmd1&&cmd2&&cmd3&&…&&cmdn
在这个程序中,前一个命令执行成功,总是后一个命令执行的必要条件。
(5)小括号和大括号
一个管道行中的简单命令,可以由小括号或大括号括起来的命令清单进行替换。
换名话说,命令清单由小括号或大括号括起来之后,可以用来取代管道行中的一个简单命令。
被括起来的全部命令的输出构成一个流(stream),这个流作为该管道行中下一个命令的输入。
{命令1参量…;命令2参量…;…;…;}|命令
常用的几个语句
介绍几个与shell过程循环有关的语句。
(1)if语句
在shell中,if语句用于表示条件的结构中,最简单的使用为:
形式一:
ifcommand-list1
thencommand-list2
fi
注意:
fi和if配对使用,fi总是放在这个条件语句的最后一行,表示if命令的结束。
command-list表示一个命令清单。
如果命令清单1执行成功,接着执行单2
形式二:
ifcommand-list1
thencommand-list2
elsecommand-list3
fi
表示:
如果命令清单1执行成功,接着执行命令清单2,然后退出;否则转去执行命
令清单3。
形式三:
ifcommand-list1
thencommand-list2
elifcommand-list3
thencommand-list4
elsecommand-list5
fi
其意义为: