1、第4章 Shell程序设计,4.1 shell概述 4.2 命令历史 4.3 名称补全 4.4 别 名 4.5 shell特殊字符 4.6 shell变量 4.7 参数置换变量,4.1 shell概述,4.1.1 shell的特点和主要版本 p82 作为命令解释程序 一种高级程序设计语言,它有变量,关键字,有各种控制语句,如if、case、while、for等语句,支持函数模块,有自己的语法结构 1.shell的特点 p 82 2shell的种类 (1)Bourne shell(简称sh) (2)C shell(简称csh) (3)Korn shell(简称ksh) (4)Bourne Aga
2、in shell(即bash),是sh的兼容增强版,4.1.2 shell程序示例p83 【例4.1】 由三条简单命令组成的shell程序(文件ex1或ex1.sh)。 $touch ex1.sh $ vi ex1,Date Pwd ps,#!/bin/bash Date Pwd ps,提示: 文件名可以保存为ex1或ex1.bash,讲上后缀更醒目 #!/bin/bash,表示下面的脚步是用bash编写的,是为了阅读的规范。,4.1.3 shell脚本的执行 p84-85 执行shell脚本的方式基本上有三种: (1)输入定向到shell脚本 # bash 脚本名 # bashex1.bas
3、h (2)以脚本名作为参数: $ bash 脚本名 参数 # bash ex1.bash (3)如果以目前shell(以表示)执行一个shell脚本,可以使用简便形式: # 脚本名 参数 # . ex1.bash(4)将shell脚本的权限设置为可执行,在提示符下执行它。 # chmod a+x ex1.bash /*设置该文件为可执行*/ # ./ex1.bash 或者将当前路径包含在PATH环境变量中 # PATH=$PATH:. 或 # PATH=$PATH:./ # ex1.bash,4.2 命令历史,命令历史文件: p85-86 专门保存在linux下曾经输入的命令 例如: $his
4、tory /*显示前面曾经输入的所有命令*/ $history 5 /*显示前面使用过的最后5行命令*/ $history c /*清除命令历史清单中所有项*/ 可用键盘的键来重复使用过去的命令.命令历史专门存放在一个隐含文件.bash_history中,他位于用户的主目录(家目录)中 例如: echo $HOME /*显示该用户的主目录*/ cd /*进入该用户的主目录*/ ls a /*查看隐含文件*/ cat .bash_history,4.3 名称补全 p88,可以输入目录名或文件名的开头部分,然后按Tab键,Linux根据输入的字母查找以这些字母开头的目录或文件,并自动补全剩余的部分
5、。,4.4 别 名,为什么要使用别名? p88 为了简化输入、方便用户。 对于常用的选项或参数较多的固定命令可采用别名4.4.1 定义别名 p88 语法格式为: alias name=value 定义别名时,往往用单引号将它代表的内容括起来,从而防止shell对其中的内容产生歧义 实例: alias /*显示系统中已经定义了哪些别名*/ alias myls=ls l a i /*定义具有多个参数的ls命令*/ myls myshare=/home/hgfs/share_file/ /*变量定义并赋值*/ Myls $myshare /* $myshare 表示引用变量的值*/ 注意:定义别名
6、时,等号“=”两边不能有空格。,4.4.2 取消别名 p89 如果想取消先前定义的别名,可使用如下命令: unalias name unalias myls可以一次将所有的别名都从别名表中删除,使用如下命令:unalias -a,4.5 shell特殊字符,4.5.1 通配符 1.一般通配符 p90 *(星号),它匹配任意字符的0次或多次出现 ?(问号),它匹配任意一个字符 (一对方括号),其中有一个字符组。其作用是匹配该字符组所限定的任何一个字符 !(惊叹号),如果它紧跟在一对方括号的左方括号()之后,则表示不在一对方括号中所列出的字符.取反,例如: *(星号):匹配任意字符的0次或多次出现
7、 匹配以f开头任意字符:f, fa, f1, fa2, ffa.s等 = f* 文件名前有圆点(.)或路径名中斜杠(/)必须显式匹配: 如想匹配 .profile .myfile .etcfile 等 = .*file 如想匹配 /etc下的所有c文件 = /etc/*.c?(问号) ab1.c abf.c abc.c abd.c = ab?.c ab?.c 不匹配 ab.c abcd.c (一对方括号) fabcd 或 fa-d 表示匹配 fa fb fc 或 fd中的任意一个 f123456789 或 f1-9 表示 f1 f2 f3 f9中的任意一个。 连字符号“-”仅在方括号内表示字符
8、范围,到了括号外就变成普通字符了;同样,?和*在括号外是通配符,到了括号内变成普通。 -a*?abc 只是表示字符串 a*abc或者 a?abc,!(惊叹号):紧跟左方括号”后面,表示取反 f!1-9.c表示以f开头,后面一个字符不是数字1到9的c文件在正则表达式中,可以同时使用”*”和“?” /usr/zhang/f?/* 表示/usr/zhang目录下,以f开头的两个字符的子目录,下的所有文件名/usr/zhang/f?/ab?d*.c 表示?Chapter0-9* 表示chapter后面跟一个0-9的数字,再跟任意个字符。书上p90表示不完全正确。,2.模式表达式 p90 包含一个或多个
9、通配符的字 *(模式表)模式表中“模式”的0次或多次出现,各模式之间以“”分开(下同) 例如: file*(.c | .o) 不匹配file.s file.h +(模式表)匹配模式表中“模式”的1次或多次出现 例如: file+(.c | .o) 不匹配file.s file.h file ?(模式表)匹配模式表中任何一种“模式”的0次或1次出现 例如: file?(.c | .o) 不匹配file.c.o file.o.c等 (模式表)仅匹配模式表中任何一种“模式”的一次出现 例如: file(.c | .o) 只匹配file.c 和 file.o !(模式表)除给定模式表中的一个“模式”之
10、外,可以匹配其他任何东西,测试模式表达式(补充内容,请备注在书上) 前提条件:在bash的shell中,要想使用模式表达式 必须使用:shopt打开了extglob选项 #shopt -s extglob /开启扩展的模式表达式 #shopt -u extglob /关闭扩展的模式表达式,4.5.2 引号 p91 1双引号 由双引号括起来的字符(除$、倒引号()和反斜线()外)均作为普通字符对待。 P91 看书分析例4.3 echo “current directory is pwd” echo “home directory is $HOME” echo “current bash shel
11、l is $SHELL” echo “file*.?” echo “directory $HOME”,2单引号 由单引号括起来的字符全部都作为普通字符出现 特殊字符$ (反引号) 反斜线()都失去原来的意义 例如: Echo echo “directory is $HOME” Echo Time is date,the file is $HOME/abc3倒引号 倒引号括起来的字符串被shell解释为命令行,在执行时,shell会先执行该命令行,并以它的标准输出结果取代整个倒引号部分。,细微的比较:echo 加双引号和不加双引号 例1:实验以下结果 #echo this is redhat l
12、inux #echo “this is redhat linux”例2:实验以下结果 #touch file.c #echo “file*.?” #echo file*.?结论:echo 加双引号和不加双引号对于普通字符串无区别,但对于正则表达式(包括通配符和模式表达式),显示结果不一样。,细微的比较:双引号和单引号的嵌套 例1:实验以下结果 echo “directory $HOME” echo directory “$HOME”,课表的实验分析: 例1. 分析以下结果 p 92 # echo current directory is pwd # echo “current director
13、y is pwd” # echo current directory is pwd例2. 实验以下结果 p92 # today=date /*变量的定义和赋值*/ # echo today is $today /*变量的引用*/例3.实验以下结果 p92 # users=who | wc l # echo The number of user is $users,4.5.3 输入/输出重定向符 Linux的shell默认状态下命令的输入流为键盘,输出流为显示器,错误输出流为显示器 我们可以使用” “” 改变默认的流向 1. “”表示输入重定向,将键盘输入改为文件 例:编写一个score_avg
14、.c的程序,file1中有10门课成绩编译score_avg.c,并执行./score_avg.exe file1,/*score_avg.c*/ main() int i,avg,score,s=0;for(i=1;i=10;i+)scanf(“%d”, ,/* file1 */ 100 76 87 65 .,2、“” 和“” 表示输出重定向 “ 表示输出重定向到文件,并覆盖文件 “” 表示输出重定向到文件,并追加文件 例如: ls l dir1 /*将当前目录的内容输入到”dir1”文件中*/ pwd dir1 /*将当前路径输入到dir1中,并覆盖*/ cat dir1 date dir
15、1 3、“”重定向命令可以配合使用 例如: ./Score_avg.exe result,4.5.4 注释、管道线和后台命令,1注释#!/bin/bash# If no arguments, then listing the current directory.# Otherwise, listing each subdirectory.2管道线ls -l $HOME | wc lls | grep m?.c | wc lcat file1 | ./score_avg.exe 3后台命令 # gcc m1.c./circle.exe &,4.5.5 命令执行操作符,1顺序执行(多命令行)
16、p97-08 pwd ; who | wc -l ; cd /usr/bin2逻辑与:命令1 & 命令2 先执行命令1,如果执行成功,才执行命令2;否则,若命令1执行不成功,则不执行命令2。 cp ex1 ex1_bak & rm ex1 3逻辑或:命令1 | 命令2 其功能是,先执行命令1,如果执行不成功,则执行命令2;否则,若命令1执行成功,则不执行命令2。 cat abc | pwd,4.6 shell变量,Shell变量有两种:环境变量和临时变量 p 99 4.6.1 用户定义的变量 1变量名 以字母或下线符打头的字母、数字和下线符序列,并且大小写字母意义不同。 2. 定义变量并赋值的
17、一般形式是: 变量名=字符串 3引用变量值 在变量名前面加上一个符号“$” 如果在赋给变量的值中要含有空格、制表符或换行符,那么,就应该用双引号把这个字符串括起来。例如: $ names=“Zhangsan Lisi Wangwu“ 如果不加引号呢?$ echo $names,实例分析: 1. #dir=/mnt/hgfs/share_file#echo $dir#echo dir2. #today=date#echo $today $Today,3.变量的值可以为字符串中的一部分,如果出现在末尾,可以直接引用。例如:#Reading and writing /*对左边ing做变量替换并显示*
18、/#s=ing#echo read$s and writ$s4.变量的值为字符串一部分,并且不是出现在末尾,要用 括起来。例如 #cat /mnt/hgfs/share_file/a.c /*想要对左边划线部分变量定义*/ #dir=“gfs/shar” #cat /mnt/h$dire_file/a.c,4命令替换 p101 将一个命令的执行结果 有两种形式的命令替换: 一种是倒引号引用命令,其一般形式是: 命令表 另一种形式是: $(命令表)如:# dir=pwd 或者 dir=$(pwd)# ls $dir,4.6.2 数组 p102,bash只提供一维数组,并且没有限定数组的大小。类似
19、与C语言,数组元素的下标由0开始编号。数组的定义: declare a 数组名数组的赋值: 数组名下标=值 数组名=(值1 值2 值n) 各个值之间以空格分开,注意是括号不是。读取数组元素值: $数组名下标 注意不能少若没有给出数组元素的下标,则数组名表示下标为0的数组元素 使用*或当作下标,则会以数组中所有元素取代*或,例如: (分析下面每条语句) declare a city city=(nanjing beijing shanghai tianjing) city3=nantong echo $city Echo $city3 Echo $city*经过实验发现: Echo $city
20、效果和 echo $city一样 但是 Echo $city3 和 echo $city3完全不一样了,4.6.4 输入/输出命令,1read命令 利用read命令从键盘上读取数据,然后赋给指定的变量。 一般格式是: read 变量1 变量2 变量个数与给定数据个数相同,则依次对应赋值变量个数少于数据个数,则从左至右对应赋值,但最后一个变量被赋予剩余的所有数据。变量个数多于给定数据个数,则依次对应赋值,而没有数据与之对应的变量取空串,例1:linux中如何转换字符到数字如两数相加? #X=12 #Y=34 #echo x+y #echo $x+$y #echo expr $x + $y /*用
21、expr去转换,+两边必须要有空格,再用反引号做命令替换*/例2:从键盘读取三个数据,并对其和显示 #Read x y z ; echo expr $x + $y + $z提示:expr的命令只能简单的计算多个变量的加减而对于复杂的计算,则要用到4.8章的方法,其中较为简单的是 echo $(x*y),2. echo命令 显示其后的变量值或者直接显示它后面的字符串 如果echo命令带有选项“-e”,那么在其后的参数中可以有以下转义字符: a b c e f n r t v m 例如: Echo e “helloa” /*响铃*/ Echo e “Login:n” ; read name 或者
22、Echo n “Login:” ; read name /*控制光标不换行,新的输入信息在该行的后面,并接受给name变量*/,【例4.6】 这是一个特洛伊木马shell脚本示例。#!/bin/bashclearcat /etc/issue /*登录计算机时,看到的登录提示*/echo -n “Login: “read namestty -echo /*设置输入不回显,不显示输入的密码*/echo -n “Password: “read passwdecho “ “ /*尝试删除此行,看看该行的作用*/stty echo /*恢复回显*/echo $name $passwd /tmp/ttt经
23、过试验,去掉stty cooked对程序也没有影响*/,4.6.5 位置参数,1位置参数及其引用 位置变量的名称很特别,分别是0,1,2, 命令行实参与脚本中位置变量的对应关系如下所示:exam1 m1 m2 m3 m4$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11引用它们的方式依次是$0, $1, $2, , $9, $10, $11等。其中,$0始终表示命令名或shell脚本名。 位置变量不能通过一般赋值的方式直接赋值通过命令行上对应位置的实参传值 实例:p107 例4.7,实例分析:例ex4.7.1 功能分析:想要统计任意两个文件(例如m1.c, m2.c)分
24、别的行数是多少?两个文件的总共的单词有多少?编写程序 #/bin/bash line1=cat m1.c | wc l /*命令替换: 命令表或$(命令表)*/ line2=cat m2.c | wc l wordnumber=cat m1.c m2.c | wc w echo “the file m1.c line number is $line1” echo “the file m2.c line number is $line2” echo “the word number of m1.c and m2.c is $wordnumber”分析,以上的shell程序可以实现功能,但是不够通
25、用,程序只针对m1.c和m2.c文件进行统计,要想实现任意两个文件的统计,需要进行改进,这就要用到位置参数。,实例分析:例ex4.7.2( 例ex4.7.1改进),#/bin/bash line1=cat m1.c | wc l line2=cat m2.c | wc l wordnumber=cat m1.c m2.c | wc w echo “the file m1.c line number is $line1” echo “the file m2.c line number is $line2” echo “the word number of m1.c and m2.c is $wo
26、rdnumber”,#/bin/bash line1=cat $1 | wc l line2=cat $2 | wc l wordnumber=cat $1 $2 | wc w echo “the file $1 line number is $line1” echo “the file $2 line number is $line2” echo “the word number of $1 and $2 is $wordnumber”,实例分析:几个参数的含义,#/bin/bash line1=cat $1 | wc l line2=cat $2 | wc l wordnumber=cat
27、 $1 $2 | wc w echo “the file $1 line number is $line1” echo “the file $2 line number is $line2” echo “the word number of $1 and $2 is $wordnumber” #- echo $0 /*$0显示命令或脚本名,即ex6*/ echo $# /* $#显示实际参数的个数(不含脚步命令本身,结果为2)*/ echo $* /* $*显示所有实参名 */,*M1.c* Main() printf(“Beginn”) ,*M2.c* #include Main() pri
28、ntf(“OK!n”);printf(“Endn”); ,*ex6* Cat $1 $2 | wc l Echo $0 Echo $1,# ex6 m1.c m2.c,Cat $1 $2 | wc l Echo $0 Echo $1 Echo $# Echo $*,=cat m1.c m2.c |wc -l,$0显示命令或脚本名,即ex6,$1显示第一个实际参数,即m1.c,$#显示实际参数的个数(不含脚步命 令本身,结果为2;$*显示所有实参名,2Set命令为位置参数赋值 Set m1.c m2.c m3.c 实际就是将m1.c赋给$1(第一个形式参数),m2.c$2, m3.c$3 例如:
29、p107 例4.8#ex7 /*执行shell脚步,实参用set定义在程序内部*/,#!/bin/bash Set m1.c m2.c Cat $1 $2 |wc -l,4.6.6 移动位置参数,P108页 shift 自学,pass,4.6.7 预先定义的特殊变量,$# 命令行上参数的个数,但不包含shell脚本名本身。因此,$#可以给出实际参数的个数。$? 上一条命令执行后的返回值(也称作 “返回码”、 “退出状态”、“退出码”等)。它是一个十进制数。(例如: cat aa; echo $?)$ 当前进程的进程号。 (例如:ps; echo $)$! 上一个后台命令对应的进程号,这是一个由
30、15位数字构成的数字串。$ 由当前shell设置的执行标志名组成的字符串。 P109 自学$* 表示在命令行中实际给出的所有实参字符串,它并不仅限于9个实参。$ 它与$*基本功能相同,即表示在命令行中给出的所有实参。但“$”与“$*”不同。 P109-110 自学,4.6.8 环境变量 4.6.9 环境文件 4.6.10 export语句与环境设置以上p110-116 自学,4.7 参数置换变量,一般的变量赋值:变量名=字符串p100 此处是另一种为变量赋值的方式,其一般形式是: 变量2=$变量1 op 字符串 /*注意=和op的两边都没空格*/ op表示操作符,它可以是下列四个操作符之一:
31、: : = : + : ? 1.变量2=$变量1:-字符串 如果变量1为空,则变量2的值=字符串;否则变量2的值=变量1的值。 例如:,#var1=nuist #var2=$var1:-hello world #Echo $var2,#var1= #var2=$var1:-hello world #Echo $var2,2.变量2=$变量1:=字符串 3.变量2=$变量1:+字符串 4.变量2=$变量1:?字符串其他2、3、4的变量赋值方法自己看书理解p117-119,4.8 算 术 运 算,从实例分析起: 输入x,y的值,求两者的差,平方和; 方法一:expr 转变 Read x y J=
32、expr $x - $y /*求两者只差*/ Echo $j K=expr $x*$x+$y*$y /*试图求两者平方和,失败*/ Echo $k该方法较为麻烦和复杂,方法二:使用let方法,简单方便 Read x y Let “j=x-y” Echo $j Let “k=x*x+y*y” Echo $k 方法三、和let的等价的方法-(算术表达式) Read x y (j=x*x+2*x*y+y*y) Echo $j注意:不能直接echo x*x+2*x*y+y*y 无法显示结果,bash中执行整数算术运算的命令是let,其语法格式为: let “算术表达式” 或者(算术表达式) 在算术表达
33、式中直接利用名称访问命名的参数,不要前面带有“$”符号 Let “j=i*6+2” = (j=i*6+2) Echo $j当表达式中有shell的特殊字符时,必须用双引号将其括起来。例如,let val=a|b使用C语言中表达式的语法、优先级和结合性。运算符见p119页的表4.3,4.9 控制结构,4.9.1 if语句 if语句用于条件控制结构中,其一般格式为:if 测试条件 if(测试条件)then 命令1 then 命令1else 命令2 fi 其中,if、then、else和fi是关键字。例如(ex9_1):if test -f “$1” /*-f 测试文件是否为普通文件*/then e
34、cho “$1 is an ordinary file . “else echo “$1 is not an ordinary file . “fi,if语句中else部分可以缺省。例如,if test -f “$1“then echo “$1 is an ordinary file . “fi if 语句的else部分还可以是elseif结构,则用关键字“elif”代替“else if”。例如(ex9_2),if test - f “$1“then pr $1 | moreelif test - d “$1“then ( cd $1 ; pr *| more ) /*此处( )为成组命令p9
35、9,或用 表示/else echo “$1 is neither a file nor a directory . “fi,if的语句的更一般形式是:if 命令表1then 命令表2else 命令表3fi其中命令表可以由一条或者多条命令组成,如果“命令表1”是由多条命令组成,测试条件以其中最后一条命令是否执行成功为准。,例4.11 cat ex10,Echo n “Type in the user name:” Read user Ifgrep $user /etc/passwd/tmp/nullwho |grep $user Thenecho “user has logged in the
36、system.cp /tmp/null tmp1rm /tmp/null Elseecho “$user has not logged in the system.” fi,4.9.2 条件测试,条件测试有三种常用形式: 1、用test 命令, 例如,测试位置参数$1是否是已存在的普通文件,可写为:#test -f “$1“ 2、用一对方括号将测试条件括起来也完全可写成: -f “$1” /*注意右边 左边空格*/ 3、 条件表达式test命令可以和多种系统运算符一起使用。当表达式的值为真时,命令返回真值0,否则返回假值非0. 文件测试运算符、 字符串测试运算符 数值测试运算符 逻辑运算符。,
37、1有关文件方面的测试 p 123,实验分析test 中-r x w的功能 原因:很多书籍以及网络上很少提及redhat linux下 test r等真实使用实例,特用实验来验证。 实验1:在root用户下创建test.c文件,并使用test r 来验证 # cd # touch test.c # ls l test r test.c /*或者 ( test r “test.c”)*/ echo $? /*分析结果*,结果为真,返回值为0/ chmod a-r test.c /*去除test.c所有的可读属性*/ test r test.c /*再次测试test.c的可读属性*/ echo $?
38、 /*结果发现,并无效果,返回值依然是0*/ 结论: test r ,test x ,test w 对超级用户root没有任何意义 原因在于:root用户对任何文件都具有绝对的控制权,即使该文件的可读属性都为空。可以尝试测试,root用户和普通用户下,当我们设置chmod a-r test.c时,用 vi test.c 时的提示信息。,实验2:在普通用户wang下创建abc.c文件,并使用test r 来验证本用户的文件 # su wang $ touch abc.c $ ls l /*显示abc.c是属于wang用户的*/ $ test r abc.c $ echo $? /*结果应返回0,
39、为真*/ $ chmod u-r abc.c /*注意此处是使用u-r,而没有用a-r*/ $ test r abc.c $ echo $? /*结果应返回1,为假*/实验3:在普通用户wang下,验证其他用户(如root)用户的可读、写# cd /home/wang /*root用户下,进入/home/wang目录创建xyz.c文件*/ # su wang $ test r xyz.c ; echo $? /* 查看一下结果*/ $ su /*再次切换到root用户,修改xyz.c的属性*/ #chmod o-r xyz.c /*注意,在root用户只修改了other用户的属性*/ # su
40、 wang $ test r xyz.c ; echo $? /* 再次查看一下结果*/ 结论:test r ,test x ,test w 对超级用户root没有任何意义; 只对普通用户下,当文件存在并且是普通用户对应角色权限可读、可写、可执行时才有效;,例1:测试条件的返回值 #test f “file1.c” 或者 # -f “file1.c” #echo $? /*显示上一条命令的返回值 0或1*/将测试条件放到if语句中的方式 If (test f “file1.c”) 相当于if(0) 或者 if(1) 或者 if test f “file1.c” /*if后面不加括号*/或者 i
41、f -r “file1.c” 或者 if( -r “file1.c” ),2有关字符串方面的测试,举例分析1: test s1 如果字符串s1非空时,测试条件为真,返回0; 如果字符串s1为空时,测试条件为假,返回1。#a=“” #test a #echo $? /*提问:此时的结果应该是什么?*/我们想象a字符串为空,应该返回1,但实际返回0的值。其原因在于:test把a看作一个字符,而此处的a实际是个变量,对变量内的值进行字符串测试,必须在变量前加$#a=“” #test $a #echo $?,例题分析2: #filename:testdir.bash #!/bin/bash DIREC
42、=$1 if ( test “ls $DIREC”) /*此题的重点在此处,利用ls 对一个存在的目录进行查看目录中有无文件*/ thenecho “$DIREC is not empty”elseecho “$DIREC is indeed empty” Fi 运行: #. testdir dirname,3有关数值方面的测试,4逻辑运算符前面三种测试条件可以在if 语句或循环语句中单个使用 也可以通过逻辑运算符把它们组合起来使用。 可以在测试语句中使用的逻辑运算符有:(1) ! 逻辑非( NOT ),取反;例如, ! -r $1 , ! test -r “$1”等。 (2) - a 逻辑与
43、( AND ),例如, - f “$myfile“ - a - r “myfile“ (3) - o 逻辑或( OR ), 例如, “$a“ -ge 0 -o “$b“ -le 100 ,4.9.3 case语句,case语句允许进行多重条件选择。其一般语法形式是:case 字符串 in模式字符串1) 命令列表;模式字符串2) 命令列表;模式字符串n) 命令列表;*) default-命令列表; esac,例1.简单的使用case(ex493_1.bash) #!/bash/bin Echo “please select number 1,2 or 3 :” Echo “1show date”
44、 Echo “2show homedir” Echo “3quit Read sele Case $sele in1)date;2)echo $HOME;3)echo “good bye” ;*)echo “this is a example for case” ; esac,# !/bin/bash # 练习 wh.bash # case 结构 hour= date +%H /*%H是取小时数目*/ case $hour in01-9|101) echo “Good morning!”;1234567) echo “Good afternoon!”;*) echo “Good evening
45、!”; esac,例2:写一段根据一天中不同时间给出问候信息的程序ex493_2.bash,如果一个模式字符串中包含多个模式,那么各个模式之间用竖线|隔开 p127,循环语句,Shell中有三种循环语句 While语句 For 语句 Until语句,4.9.4 while语句,while语句的一般形式是:while 测试条件 do命令表done 执行过程: 先进行测试条件,如果结果为真,进入循环体(do-done),执行循环体中的命令,然后再做条件测试,直到测试为假,退出循环 提示: 测试条件部分除使用test命令或等价的方括号外,还可以是一组命令。根据其最后一个命令的执行结果决定是否进入循环
46、体执行。,例:ex494.bash 功能:显示一批存在的普通文件的内容 #!/bin/bash while $1 /*测试第一个形式参数是否为空*/ doif -f $1 then echo “display:$1”cat $1else echo “$1 is not a file name.”fishift Done 执行方式: . ex494.bash file1 file2 file3,4.9.5 until语句,until语句的一般形式是:until 测试条件do命令表done 它与while语句很相似,只是测试条件不同:当测试条件为假时,才进入循环体,直至测试条件为真时终止循环。 不
47、举例,4.9.6 for语句,其使用方式主要有两种:一种是值表方式,另一种是算术表达式方式。1For循环的算术表达式方式 其一般格式是:for ( e1;e2;e3) ; do 命令表;done 或者for (e1;e2;e3)do命令表done 其中,e1, e2, e3是算术表达式。它的执行过程与C语言中for语句相似,例如:ex496_1.bash #!/bin/bash s=0 for(i=1;i=10;i+)do(s=s+i)done echo “the sum is $s”,2、for循环的值表达方式: 根据循环变量的取值方式可以分为三种: 格式一、值表的方式for 变量 in 值表 ;do 命令表;done 此时循环变量的值来源于所有的给定的值表。例如:show_city.bash(ex496_2.bash) #!/bin/bash declare a city city=(nanjing beijing shanghai tianjing) for k in “$city*”; do echo $k; done,