第7章shell程序设计把命令有机地组合在一起,形成功能强大、使用灵活,但代码简单的新命令,极大地提高了用户管理使用Unix/Linux系统的工作效率。其它shell与Bash版本的shell也十分类似,读者可以举一反三,根据需要自学其他的shell。shell脚本的建立与执行shell脚本的建立同建立普通文本文件的方式相同,可利用编辑器vi或cat命令,进行程序录入和编辑加工。shell脚本的执行sh脚本名sh脚本名改执行权限后直接执行方式shell的变量~可写的shell环境变量可写的shell环境变量可以对它们进行赋值,大部分可写的shell环境变量都在登录过程中执行“/etc/profile”文件时进行初始化。该文件由系统管理员设置,用于为系统上的所有用户建立一个公共环境。例:HOMEMAILPATHPS1TERM特殊的环境变量$*所有命令行参数的值$#命令行参数的总数$$当前进程的进程ID(PID)$?最后执行的一条命令的退出状态,返回值为0则成功,非0则失败$!在后台运行的最后一个进程的进程ID位置参数在命令行传递给shell脚本的参数。共有十个位置参数,依次是$O,$1,$2,…,$9必有$0;而其他位置参数依据实际需求,可有可无。输出位置参数可以用echo命令输出位置参数位置参数用set命令给位置参数赋值移动位置参数如果实际给定的命令行参数多于9个,就需要用shift命令移动位置参数。shift命令可以带有一个整数作为参数,例如:shift3其功能是每次把位置参数左移3位。如果未带参数,则默认值为l。用户自定义变量在shell编程语言中无须声明和初始化shell变量,一个未初始化的shell变量,其默认的初始化值为空字符串。用户定义的shell变量名是由字母或下线符打头的字母、数字和下线符序列,并且大小写字母意义不同。这与C语言中标识符的定义相同。定义变量并赋值的形式字符串赋值,格式如下:变量名=字符串如果在赋给变量的值中要含有空格、制表符或换行符,那么就应该用双引号把这个字符串括起来。变量值可以作为某个长字符串中的一部分。如果它在长字符串的末尾,就可以利用直接引用形式。查看变量使用变量用env命令可以查看环境变量用不带参数的set命令可以显示所有“shell变量(包括用户自定义变量)名以及它们的当前值。set命令还可用于改变一些只读shell环境变量的值。在程序中使用变量值时,要在变量名前面加上一个符号“$”。这个符号告诉shell,要取出其后变量的值。7.3shell中的特殊字符特殊字符有着重要的作用。包括:通配符引号命令执行顺序操作符注释符、反斜线及后台操作符在使用时应注意它们表示的意义和作用范围。shell的通配符星号(*)问号(?)一对方括号([])感叹号(!)shell的引号双引号(“”)单引号(‘’)倒引号(``)倒引号的嵌套应用,倒引号的嵌套时必须在内层的一组倒引号用反斜线(\)进行转义。命令执行顺序操作符顺序执行顺序分隔符(;)管道线(|)逻辑与(&&)逻辑或(||)shell中的注释符、反斜线及后台操作符注释符(#)反斜线(\)转义符,它能把特殊字符变成普通字符。还作为续行符使用。如果把它放在一行的回车换行之前那么表示下一行接续此行,与下一行被视为同一行,可用于表示长的输入行。后台操作符(&)7.4shell编程中的输入输出命令shell中输入输出的标准文件每个进程运行时自动打开三个文件,这些文件称为命令的标准文件,分别用于命令读取输入、输出结果以及输出错误消息,即标准输入文件(stdin)标准输出文件(stdout)标准错误输出文件(stderr)shell的输入输出重定向命令2shell的输入输出命令read命令用read命令由标准输入读取数据,然后赋给指定的变量。其一般格式如下。read变量1[变量2]……echo命令echo命令是将其后的参数输出。最好用双引号把所有参数括起来,这样不仅易读并且能使shell对它们进行正确的解释。7.5shell程序控制结构语句脚本的控制结构语句有三种基本的类型:两路分支、多路分支以及一个或多个命令的循环执行。Linux的bash中的两路分支语句是if语句,多路分支语句是if-elif和case语句;代码的循环执行语句是for、while和until语句。if语句两路分支的if语句格式:if判断条件then命令1else命令2Fi判断条件包括命令语句和测试语句两种方式:命令语句形式的判断条件多路条件判断分支的if语句格式为:if判断条件1then命令1elif判断条件2then命令2……else命令nFi其中elif是elseif的缩写测试语句有两种格式,一种是使用关键字test,而另一种是使用方括号。格式如下:testexpression[expression]二者是等效的。同时要注意几点用于三种形式的测试:文件测试、字符串测试和数值测试文件测试参数功能-rfile若文件存在并且是用户可读的,则测试条件为真-wfile若文件存在并且是用户可写的,则测试条件为真-xfile若文件存在并且是用户可执行的,则测试条件为真-ffile若文件存在并且是普通文件,则测试条件为真-dfile若文件存在并且是目录文件,则测试条件为真-pfile若文件存在并且是FIFO文件,则测试条件为真-sfile若文件存在并且不是空文件,则测试条件为真字符串测试参数功能str如果字符串str不是空字符串,则测试条件为真str1=str2如果strl等于str2,则测试条件为真(注意,“=”前后须有空格)str1!=str2如果str1不等于str2,则测试条件为真-nstr如果字符串str的长度不为0,则测试条件为真-zstr如果字符串str的长度为O,则测试条件为真数值测试参数功能n1–eqn2如果整数n1等于n2(n1=n2),则测试条件为真n1–nen2如果整数nl不等于n2(n1n2),则测试条件为真n1–ltn2如果n1小于n2(n1n2),则测试条件为真n1–len2如果n1小于等于n2(n1=n2),则测试条件为真n1–gtn2如果n1大于n2(n1n2),则测试条件为真n1–gen2如果nl大于等于n2(n1=n2),则测试条件为真用逻辑操作符进行组合的测试语句参数功能!逻辑非,放在任意逻辑表达式之前,原来真的表达式变为假,原来假的变为真-a逻辑与,放在两个逻辑表达式之间,仅当两个逻辑表达式都为真时,结果才为真-o逻辑或,放在两个逻辑表达式之间,其中只要有一个逻辑表达式为真时,结果就为真()圆括号,用于将表达式分组,优先得到结果。括号前后应有空格并用转义符“\(”和“\)”用逻辑操作符进行组合的测试语句实例[!$s1-le0]!test$s1-le0[-f$s1–a–w$s1]test–f$s1-a–w$s1[$s1–gt0–o$s2–lt10]test$s1–gt0–o$s2–lt10[\($a–gt0–a$a–lt10\)–a$a–ne5]test\($a–gt0–a$a–lt10\)–a$a–ne5case语句对同一变量进行多次的测试,比elif语句更简单、简洁casestring1instr1)commands-list1;;str2)commands-list2;;...strn)commands-listn;;esac使用case语句时应注意以下几点(1)每个正则表达式后面可有一条或多条命令,其最后一条命令必须以两个分号(;;)结束。(2)正则表达式中可以使用通配符。(3)如果一个正则表达式是由多个模式组成,那么各模式之间应以竖线“|”隔开。表示各模式是“或”关系,即只要给定字符串与其中一个模式相配,就会执行其后的命令表。使用case语句时应注意以下几点(4)各正则表达式是唯一的,不应重复出现。(5)case语句以关键字case开头,以关键字esac结束。(6)case的退出(返回)值是整个结构中最后执行的那个命令的退出值。若没有执行任何命令,则退出值为零。for语句格式:forvariable[inargument-list]docommand-listDone其中的[inargument-list]部分为可选项,由于它的不同又可有三种形式。[inargument-list]部分三种形式[argument-list]为变量值表变量variable依次取值表中各字符串[argument-list]为文件的表达式变量的值依次取当前目录(或指定目录)下与文件表达式相匹配的文件名,每取值一次,就进入循环体执行命令表,直到所有匹配的文件名取完为止。[argument-list]为空[argument-list]也可以用$*来代替,变量依次取位置参数的值,然后执行循环体中的命令表,直至所有位置参数取完为止。while语句格式为:whileexpressiondocommand-listDone作用:只要expression的值为真,则进入循环体,执行command-1ist中的命令,然后再做条件测试,直到测试条件为假时才终止while语句的行。until语句格式为:untilexpressiondocommand-listdone作用:只要expression的值为假,就执行command—lists的命令。break和continue语句break命令可以从循环体中退出来。格式为:break[n]continue命令跳过循环体中在它之后的语句,回到本层循环的开头,进行下一次循环。格式为:continue[n]算术表达式五种基本的算术运算:+(加)、-(减)、\*(乘)、/(除)和%(取模)。shell只提供整数的运算。格式如下:exprn1运算符n2例:[expr15\*15注意:在运算符的前后都留有空格,否则expr不对表达式进行计算,而直接输出它们。自定义函数在shell脚本中可以定义并使用函数。其定义格式为:Function(){command-list}函数应先定义,后使用。调用函数时,直接利用函数名调用。ENDOFCHAPTER7