同传统的编程语言一样,Shell提供了很多特性,这些特性可以使Shell Script编程更为有用,如:数据变量、参数传递、判断、流程控制、数据输入/输出和函数等。
9.1.1 Shell脚本的建立和执行
Shell程序是解释执行的。
按照Shell编程的惯例,以bash为例,程序的第一行一般为“#!/bin/bash”,
其中#表示该行是注释,
叹号!告诉Shell运行叹号之后的命令,即运行/bin/bash,并让/bin/bash去执行Shell脚本文件中的内容。
执行Shell程序有3种方法:
方法1.
格式:bash Shell程序名 [参数]
方法2.
格式:bash < Shell程序名
方法3.
用chmod命令使Shell程序成为可执行文件
搜索路径(如,/bin、/usr/bin、/sbin、/usr/sbin等)
通过“./Shell程序名”的方式来执行。
9.1.2 Shell变量变量是代表某些值的符号,在计算机语言中可以使用变量进行多种运算和控制。Shell有四种变量:用户自定义变量,环境变量,预定义变量和位置变量。
1.用户自定义变量用户定义自己变量的语法规则是:变量名=变量值。
在定义变量时,变量名前不应加符号$,在引用变量的内容时则应在变量名前加$;在给变量赋值时,等号两边一定不能留空格,若变量中本身就包含了空格,则整个字符串都要用双引号括起来。在编写Shell程序时,为了使变量名和命令名相区别,建议所有的变量名都用大写字母来表示。
有条件的变量替换:在bash中可以使变量替换在特定条件下执行,即有条件的变量替换。这种变量替换总是用大括号括起来的。
实例9-2 使用用户自定义变量以及变量替换功能
Shell提供了参数置换功能,以便用户可以根据不同的条件来给变量赋不同的值。参数置换的变量有4种,这些变量通常与某一个位置参数相联系,根据指定的位置参数是否已经设置,来决定变量的取值,他们的语法和功能见表9-1。
表9-1 参数置换的语法和功能语法
功能
变量=${参数:-word}
如果设置了参数,则用参数的值置换变量的值,否则用word置换。即这种变量的值等于某一个参数的值,如果该参数没有设置,则变量就等于word的值
变量=${参数:=word}
如果设置了参数,则用参数的值置换变量的值,否则把变量设置成word,然后再用word替换参数的值。注意,位置参数不能用于这种方式,因为在Shell程序中不能为位置参数赋值
变量=${参数:?word}
如果设置了参数,则用参数的值置换变量的值,否则就显示word并从Shell中退出,如果省略了word,则显示标准信息。这种变量要求一定等于某一个参数的值。如果该参数没有设置,就显示一个信息,然后退出,因此这种方式常用于出错指示
变量=${参数:+word}
如果设置了参数,则用word置换变量,否则不进行置换
实例9-3 使用参数置换功能
2.环境变量
Linux是一个多用户的操作系统。多用户意味着每个用户登录系统后,都有自己专用的运行环境(也称为Shell环境)。而这个环境是由一组变量及其值组成,他们决定了用户环境的外观,这组变量被称为环境变量。环境变量和Shell紧密相关,用户可以通过Shell命令对自己的环境变量进行修改以达到对环境的要求。环境变量又可以被所有当前用户所运行的程序使用。对于bash来说,可以通过变量名来访问相应的环境变量,例如:#echo?$HOME。
Shell在开始执行时,就已经定义了一些和系统的工作环境有关的变量,用户还可以重新定义这些变量,也可以通过修改一些相关的环境定义文件来修改环境变量,在RHEL中,与环境变量有关的文件有:/etc/profile、/etc/bashrc、~/.bash_profile和~/.bashrc等,修改完毕后,重新登录或者执行命令source filename,即可使修改的环境变量生效。
常用的Shell环境变量及其功能见表9-2。
 注意:
如果要使用环境变量或其他Shell变量的值,必须在变量名之前加上一个“$”符号,不能直接使用变量名。显示环境变量的命令有env和set等命令。
表9-2 环境变量及其功能环境变量
功能
BASH
当前运行的shell的实例的路径名
BASH_VERSINFO
shell的版本号
CDPATH
用于cd命令的搜索路径,“.”不用单独设置,永远被包含
COLUMNS
终端的列数
EDITOR
编辑器
HOME
用于保存当前用户主目录的完全路径名
HISTFILE
指示当前的bash所用的历史文件
HISTSIZE
历史命令记录数
HOSTNAME
主机的名称
IFS
Internal Field Separator,默认为空格,tab及换行符
LANGUAGE
语言相关的环境变量,多语言可以修改此环境变量
LINES
终端的行数
LOGNAME
当前用户的登录名?
MAIL
当前用户的邮件存放目录?
OLDPWD
上一个工作目录
PATH
用于保存用冒号分隔的目录路径名,决定了shell将到哪些目录中寻找命令或程序,Shell将按PATH变量中给出的顺序搜索这些目录,找到的第一个与命令名称一致的可执行文件将被执行
PS1
主提示符,root用户的默认主提示符是“#”,普通用户的默认主提示符是“$”
PS2
在Shell接收用户输入命令的过程中,如果用户在输入行的末尾输入“\”然后回车,或者当用户按回车键时Shell判断出用户输入的命令没有结束时,就显示这个辅助提示符,提示用户继续输入命令的其余部分,默认的辅助提示符是“>”
PWD
当前工作目录的绝对路径名,该变量的取值随cd命令的使用而变化
SECONDS
启动的秒数
SHELL
前用户Shell类型,也指出Shell解释程序放在什么地方
TERM
终端的类型
UID
当前用户的识别字,取值是由数位构成的字串
3.预定义变量预定义变量和环境变量类似,也是在Shell一开始时就定义的变量。所不同的是,用户只能根据Shell的定义来使用这些变量,而不能重定义他们。所有预定义变量都是由$符和另一个符号组成的,常用的Shell预定义变量及其含义见表9-3。
表9-3 预定义变量及其含义预定义变量
含义
$0
当前执行的进程名
$!
后台运行的最后一个进程的进程号(PID)
$?
命令执行后返回的状态,即上一个命令的返回代码,用于检查上一个命令执行是否正确,命令退出状态为0表示该命令正确执行,任何非0值表示命令出错
$*
所有位置参数(命令行参数)的值,即传递给程序的所有参数组成的字符串
$#
位置参数(命令行参数)的数量,即传递给程序的总的参数数目
$$
当前进程的进程号(PID)
$-
使用set及执行时传递给Shell的标志位
$@
所有位置参数(命令行参数)的值,个别的用双引号括起来
4.位置变量位置变量是一种在调用Shell程序的命令行中,按照各自的位置决定的变量,是在程序名之后输入的参数。位置变量之间用空格分隔,Shell取第一个位置变量替换程序文件中的$1,第二个替换$2,依次类推。$0是一个特殊的变量,它的内容是当前这个Shell程序的文件名,所以,$0不是一个位置变量,在显示当前所有的位置变量时是不包括$0的。
9.1.3 控制Shell提示符可以指定一个或者多个特殊字符作为提示符变量。特殊字符及其含义见表9-4。
表9-4 特殊字符及其含义特殊字符
说明
\!
显示该命令的历史记录编号
\#
显示当前命令的命令编号
\$
显示$符作为提示符,如果用户是root的话,则显示#号
\\
显示反斜杠
\@
12小时制时间,带am/pm
\d
日期,格式为:weekday month date
\h
主机名的第一部分(第一个“.”前面的部分)
\H
主机名的全称
\n
回车和换行
\s
当前用户使用的shell的名字
\t
时间,格式为hh:mm:ss,24小时格式
\T
时间,格式为hh:mm:ss,12小时格式
\u
当前用户的用户名
\v
shell的版本号
\V
shell的版本号(包括补丁级别)
\W
当前的工作目录
[root@localhost sh_script]# PS1='\s-\v\$'
设置了PS1的值(PS1='\s-\v\$')后,命令行提示符变成“bash-3.2#”,如下行:
bash-3.2#echo $PS1
\s-\v\$
bash-3.2#PS1='[\u@\h \W]\$ '
重新设置了PS1的值(PS1='[\u@\h \W]\$ ')后,命令行提示符变成“[root@localhost sh_script]”,如下行:
[root@localhost sh_script]# echo $PS1
[\u@\h \W]\$
[root@localhost sh_script]#
请读者结合表9-4对上面内容进行分析。
9.1.4 测试命令与传统语言不同的是,Shell不是用布尔运算表达式来指定条件值,而是用命令和字符串。使用test命令进行条件测试格式:test 测试表达式。
test命令在以下4种情况下使用:
1.两个整数值的比较;
2.字符比较;
3.文件操作,如文件是否存在及读写权限等状态;
4.逻辑操作,可以进行逻辑“与”,“或”操作,通常与其他条件联合使用。常用的测试符及其相应的功能见表9-5。
表9-5 测试符及其相应的功能数值测试
字串测试
文件测试
选项
功能
选项
功能
选项
功能
-eq
等于,则为真
=
等于,则为真
-b文件名
如果文件存在且为块特殊文件,则为真
-ge
大于等于,则为真
!=
不相等,则为真
-c文件名
如果文件存在且为字符型特殊文件,则为真
-gt
大于,则为真
-z 字串
字串长度为零,则为真
-d文件名
如果文件存在且为目录,则为真
-le
小于等于,则为真
-n字串
字串长度不为零,则为真
-e文件名
如果文件存在,则为真
-lt
小于,则为真
-f文件名
如果文件存在且为普通文件,则为真
-ne
不等于,则为真
-r文件名
如果文件存在且可读,则为真
-s文件名
如果文件存在且至少有一个字符,则为真
-w文件名
如果文件存在且可写,则为真
-x文件名
如果文件存在且可执行,则为真
实例9-4 使用测试命令
4.逻辑操作在Shell脚本中,一般情况一条命令占一行,但有时也可以多条命令在一行中,他们可能顺序执行,也可能在相邻的命令之间存在逻辑关系。
(1)&&
格式为:command1 && command2。
在一个命令行中,命令之间也可以用逻辑“与”操作符“&&”连接起来,实现命令执行时的逻辑“与”运算。仅当前一条命令执行成功时才执行后一条命令。
(2)||
格式为:command1 || command2。
在一个命令行中,命令之间也可以用逻辑“或”操作符“||”连接起来,实现命令执行时的逻辑“或”运算。仅当前一条命令执行出错时才执行后一条命令。
(3)混合逻辑混合逻辑格式1:command1 && command2 && command3。
仅当command1,command2执行成功时才执行command3
混合逻辑格式2:command1 && command2 || comamnd3。
仅当command1执行成功,command2执行失败时才执行command3
读者可以根据实际需要进行多种条件命令的组合。
5.进行test测试的标准方法因为test命令在 Shell编程中占有很重要的地位,为了使Shell能同其他编程语言一样便于阅读和组织,bash在使用test测试时使用了另一种方法,用方括号将整个test测试括起来。格式为:[ test测试 ]
 注意:
,[”后与“]”前一定要有空格。
9.1.5 算术运算
bash提供了简单的整数算术运算,格式为:$[表达式]
表达式是由整数,变量和运算符组成的有意义的式子。
bash也提供3种逻辑运算符。可以将命令连接起来,分别为:逻辑非”!”,逻辑与”&&”和逻辑或”||”。他们的优先级为:”!”最高,”&&”次之,”||”最底。
bash也允许使用圆括号使一个表达式成为整体,圆括号优先级最高。
实例9-5 进行算术运算
9.1.6 内部命令
bash命令解释程序包含一些内部命令,内部命令在目录列表时是看不见的,他们由Shell本身提供。常用的内部命令有:echo、eval、exec、exit、export、read、readonly、shift、wait和“.”。