Shell脚本是含有若干UNIX命令或可执行程序的文本文件。
1 运行Shell脚本
Shell脚本有两种运行方式,第一种方式是利用sh命令,把shell脚本文件名作为参数。这种执行方式要求shell脚本文件具有“可读”的访问权限。
第二种执行方式是利用chmod命令设置shell脚本文件,使shell脚本具有“可执行”的访问权限。然后直接在命令提示符下输入shell脚本文件名。
2 退出或出口状态
一个UNIX进程或命令终止运行时,将会自动地向父进程返回一个出口状态。如果进程成功执行完毕,将会返回一个数值为0的出口状态。如果进程在执行过程中出现异常而未正常结束时,将会返回一个非零值得出错代码。
在shell脚本中,可以利用“exit[n]”命令在终止执行shell脚本的同时,向调用脚本的父进程返回一个数值为n的shell脚本出口状态。其中,n必须是一个位于0-255范围内的整数值。如果shell脚本是以不带参数的exit语句结束执行时,shell脚本的出口状态就是脚本中最后执行的一条命令的出口状态。
UNIX系统中为了测试一个命令或shell脚本的执行结果,$?内部变量返回之前执行的最后一条命令的出口状态。
3 调用适当的shell解释程序
shell脚本的第一行均包含一个以#!为起始标志的文本行,这个特殊的起始标志表示当前文件包含一组命令,需要提交给指定的shell解释执行。紧随#!标志的是一个路径名,指向执行当前shell脚本文件的命令解释程序。如:
#!/usr/bin/ksh
如果shell脚本中包含多个特殊的标志行,只有一个标志行起作用。
4 变量
shell变量名可以由任何字母、数字和下划线等字符组成,但第一个字符必须是字母或下划线。
shell中的所有变量都是字符串类型的,shell并不区分变量的类型。
从用途上考虑,变量可以分为内部变量、本地变量、环境变量、参数变量和用户定义的变量。
内部变量是为便于shell编程而由shell设定的变量。如错误类型的ERRNO变量。
本地变量是在代码块或函数中定义的变量,且仅在定义的范围内有效的变量。
参数变量是调用shell脚本或函数时传递的变量。
环境变量是为系统内核、系统命令和用户命令提供运行环境而设定的变量。
用户定义的变量是为运行用户程序或完成某种特定的任务而设定的普通变量或临时变量。
5 变量的赋值
变量的赋值可以采用赋值运算符=实现,其语法格式:variable=value。赋值运算符前后不能有空格,未初始化的变量的值为null,使用下列变量赋值的形式,即可声明一个未初始化的变量:variable=
6 内部变量
shell提供了丰富的内部变量,为用户的shell编程提供支持。
PWD,表示当前的工作目录,其变量值等同于pwd内部命令的输出。
RANDOM,每次引用这个变量时,将会生成一个均匀分布的0-32767范围内的随机整数。
SCONDS,脚本已经运行的时间(秒)。
PPID,当前进程的父进程的进程ID。
?,$?变量表示最近一次执行的命令或shell脚本的出口状态。
7 环境变量
EDITOR,用于确定命令行编辑所用的编辑程序,通常为vi
HOME,用户主目录
PATH,指定命令的检索路径。
8 变量的引用和替换
假定variable是一个变量,在变量名字前加上“$”前缀符号即可引用变量的值,即使用变量中存储的值来替换变量名字本身。
引用变量的几种形式:$variable与${variable}
注意:位于双引号中的变量可以进行替换但位于单引号中的变量不能进行替换。
9 变量的间接引用
假定一个变量的值是另一个变量的名字,根据第一个变量可以取得第三个变量的值。如:message=hello
hello="good morning" 使用echo "now message=/$$message"将返回now message=good morning。
${var:=value},如果变量var未设置或其值为null,则使用value为变量var赋值,并进行变量替换。
${var=value},不管var是否有值,都将使用value进行替换。
10 位置参数
从命令行上传递给shell脚本的参数,传递给函数的参数或通过set命令得到的参数通称为位置参数。位置参数出现的顺序按序号引用$0、$1、$2.....,故称位置参数。
$0是shell脚本文件的名字,由shell进程负责设置$0的参数。
$1是第一个参数,$2是第二个参数....以此类推。但从第十个位置参数开始,必须使用花括号括起来。如:${10}。
特殊变量$*和$@表示所有的位置参数,$#表示位置参数的总数。
通过set命令来设置位置参数的值,如:set a b c 将设置$1,$2,$3分别为a、b、c。而我们使用命令echo $*将输出所有已被设置的命令参数的值。
11 变量声明与类型定义
尽管shell并不严格的区分变量的类型,但在korn shell和Bash中,可以使用typeset或declare命令定义变量的类型,并可以在定义时进行初始化。
korn shell使用typeset设定变量的属性。利用typeset命令的-i选型可以把变量声明为整数变量。如:
typeset -i number
number=3
echo "number=$number"
12 部分命令介绍
:与true语句不执行任何实际的处理动作,但可用于返回一个出口状态为0的测试条件。这两个语句常用于while循环结构的无限循环测试条件。
echo与print命令,print的功能与echo的功能完全一样。主要用于显示各种信息。
read命令,read语句的主要功能是读取标准输入的数据,然后存储到变量参数中。如果read命令后面有多个变量参数,输入的数据将按空格分隔单词顺序依次为每个变量赋值。read语句的变量参数后面还可以附加提示字符串。如:read data?"please enter data"
set与unset命令,set命令是修改或重新设置位置参数的值。shell规定,用户不能直接为位置参数赋值。使用不带参数的set将会输出所有内部变量。
set --,清除所有的位置参数。
unset命令,用于清除shell变量,把变量的值设置为null。这个命令并不影响位置参数。
expr命令用于计算表达式的值,然后把计算结果送到标注输出。其中表达式可以是字符串比较表达式、整数算术表达式或模式匹配表达式。语法格式:expr expression
expr命令支持的整数算术运算表达式:
exp1+exp2,计算表达式exp1和exp2的和
exp1-exp2,计算表达式exp1和exp2的差
exp1/*exp2,计算表达式exp1和exp2的乘积
exp1/exp2,计算表达式exp1和exp2的商
exp1%exp2,计算表达式exp1与exp2的余数
expr命令支持的字符串比较表达式:
str1=str2,比较字符串str1等于str2,如果计算结果真,同时输出1,但返回值为0。反之计算结果为假,则输出0,但返回1。
另外的一些比较运算符:/>、/<、/>=、/<=、!=
let命令取代并扩展了expr命令的整数算术运算。let命令除了expr支持的五种算术运算外,let命令还支持+=、-=、*=、/=、%=
13 数值常数
shell脚本按十进制解释字符串中的数字字符,除非数字前有特殊的前缀或记号。若数字前有一个0则表示一个八进制的数,0x或0X表示一个十六进制的数。BASE#number表示以BASE(2-64)为底数,以number为的数值。如:
let "oct=032"
echo "oct number=$oct"
let "bin=2#1010"
echo "binary number=$bin"
14 命令替换
命令替换的目的是获取命令的输出,为变量赋值或对命令的输出作进一步的处理。命令替换实现的方法:采用$(...)形式引用命令或使用反向引号引用命令,'command'
如:
today=$(date)
echo $today
删除文件filename中包含需要删除的文件列表。rm $(cat filename)
15 test语句
test语句与if/then和case结构语句一起,构成了shell编程的控制转移结构。
test命令的主要功能是计算紧随其后的表达式,检查文件的属性、比较字符串或比较字符串内涵的整数值,然后以表达式的计算结果作为test命令的出口状态。如果test命令的出口状态为真则返回0,如果为假则返回一个非0的数值。
test命令的语法格式有:test expression或[ expression ],注意方括号内侧的两边必须各有一个空格。
[[ expression ]]是一种比[ expression ]更通用的测试结构,也是扩展了test命令。
16 文件测试运算符
文件测试主要指文件的状态和属性测试,其中包括文件是否存在,文件的类型、文件的访问权限以及其他属性等。
文件属性测试表达式
-a file,如果给定的文件存在,则条件测试的结果为真。
-r file,如果给定的文件存在,且其访问权限是当前用户可读的,则条件测试的结果为真。
-w file,如果给定的文件存在,且其访问权限是当前用户可写的,则条件测试的结果为真。
-x file,如果给定的文件存在,且其访问权限是当前用户可执行的,则条件测试的结果为真。
-s file,如果给定的文件存在,且其大小大于0,则条件测试的结果为真。
-f file,如果给定的文件存在,且是一个普通文件,则条件测试的结果为真。
-d file,如果给定的文件存在,且是一个目录,则条件测试的结果为真。
-L file,如果给定的文件存在,且是一个符号链接文件,则条件测试的结果为真。
-c file,如果给定的文件存在,且是字符特殊文件,则条件测试的结果为真。
-b file,如果给定的文件存在,且是块特殊文件,则条件测试的结果为真。
-p file,如果给定的文件存在,且是命名的管道文件,则条件测试的结果为真。
f1 -ed f2,如果给定的文件f1和f2存在且指向的是同一个物理文件,则条件测试的结果为真。
字符串测试运算符
-z str,如果给定的字符串的长度为0,则条件的结果为真。
-n str,如果给定的字符串的长度大于0,则条件测试的结果为真。要求字符串必须加引号。
s1=s2,如果给定的字符串s1等同于字符串s2,则条件测试的结果为真。
s1!=s2,如果给定的字符串s1不等同于字符串s2,则条件测试的结果为真。
s1<s2,如果给定的字符串s1小于字符串s2,则条件测试的结果为真。例:
if[[ "$a"<"Sb" ]]
if[[ "$a"/<"$b" ]],在单方括号情况下,字符<和>前须加转义符号。
s1>s2,若给定的字符串s1大于字符串s2,则条件测试的结果为真。
在比较字符串的test语句中,变量或字符串表达式前后一定要加双引号。
整数值测试运算符
test语句中整数值的比较自动采用的是c语言中的atoi()函数,把字符转换成等价的ASC整数值。所以可以使用数字字符串和整数值进行比较。
整数测试表达式:-eq(等于),-ne(不等于),-gt(大于),-lt(小于),-ge(大于等于),-le(小于等于)
17 逻辑运算符
(expression),用于计算括号中的组合表达式,如果整个表达式的计算结果为真,则测试结果也为真。
!exp,对表达式进行逻辑非运算,即对测试结果求反。例:test ! -f file1
符号-a或&&表示逻辑与运算,符号-o或||表示逻辑或运算。
==============================================================================
参考拓展:
Linux Make(Makefile)由浅入深的学习与示例剖析