1、Shell编程09榆林职业技术学院 杨浩与应用实践1学习目标1.会使用基本正则表达式。2.掌握cut、awk字符串截取命令、sed轻量级编辑工具以及printf格式化输出命令的基本使用方法。3.熟练掌握排序命令sort、统计命令wc等字符串处理命令的使用方法。4.熟练掌握条件判断命令和多重条件判断命令的使用方法。5.熟练掌握单分支、两分支、多分支if选择语句的使用方法。6.熟练掌握case多分支选择语句的使用方法。7.熟练掌握for循环语句、while循环语句和until循环语句的使用方法。本章学习目标29.1 正则表达式39.1.1 正则表达式与通配符 通配符是用于匹配文件名的,是对文件进行
2、批量操作的。如:#显示以“zheng”开头的任意长度的文件名:rootlocalhost temp#ls zheng*#显示以“zheng”开头、长度为6、第六个字符为任意字符的文件名:rootlocalhost temp#ls zheng?#显示以“zhengze”开头、长度为8、第八个字符为“1”或者“2”或者“3”的文件名:rootlocalhost temp#ls zhengze123 正则表达式是对文件内容操作时,用来匹配文件中的字符串的。比如,grep、awk、sed等命令都是处理文件内容的,都支持正则表达式,用于在文件中查找满足一定条件内容。9.1 正则表达式49.1.1 基本正
3、则表达式 shell编程中有基本正则表达式和扩展正则表达式,本书只介绍基本正则表达式,其符号和功能如下表所示。符号功能*表示*前的这个字符匹配任意多次(包括0次)。如:s*,0个或任意多个的“s”。.匹配除换行符以外的其它任意一个字符如:b.*h,表示以“b”开头、以“h”结尾、且中间为任意多个任意字符的字符串。匹配以后第一个字符串开头的行。如:ruler,表示以“ruler”开头的行。$匹配以符号“$”前第一个字符串结尾的行。如:ruler$,表示以“ruler”结尾的行。符号功能 匹配括号中的任意一个字符(但不匹配回车符)。如:ruler,表示匹配“ruler”这五个字符中的任何一个;1-
4、9,表示匹配1-9中九个数字的任何一个数字;1-9A-Z,表示表示匹配两个字符,第一个字符是1-9中的任何数字,第二个字符是任何一个大写字母。取反,匹配除括号中字符以外的任何字符。如:0-9表示匹配除0-9之外的任意字符。转义字符。n表示其前面的字符出现n次。如:a-z5表示任意5个小写字母。13-90-99,表示手机号码,第一位是1,第二位是3-9的任意数字,后九位数是任意数字。n,表示其前面的字符至少出现n次。如:1353,表示由1,3,5组成的任意三位或以上位数的数字。n,m表示其前面的字符至少出现n次,最多出现m次。如:a-z6,8表示匹配6-8位的任意小写字母。9.1 正则表达式59
5、.1.1 基本正则表达式 例9.1 可用如下命令在ruler文件中查找至少包含两个连续“o”字符的行:rootlocalhost temp#grep“ooo*”ruler 例9.2 在ruler文件中查找包含第一个字符为“r”、第四个字符为“t”、第二、第三个字符为任意字符的字符串的行,可用如下命令:rootlocalhost temp#grep”r.t”ruler 例9.3 在ruler文件中查找包含第一个字符为“p”、最后一个字符为“n”的字符串的行,可用如下命令:rootlocalhost temp#grep”p.*n”ruler 例9.4 可用如下命令在ruler文件中查找空行,并返回
6、行号:rootlocalhost temp#grep -n”$”ruler 例9.5 可用如下命令在ruler文件中查找以非数字开头的行,并返回行号:rootlocalhost temp#grep -n “0-9”ruler 例9.6 可用如下命令在ruler文件中查找不以字母开头的行:rootlocalhost temp#grep “a-zA-Z”ruler 例9.7 可用如下命令在ruler文件中查找以“$”结尾的行:rootlocalhost temp#grep “$”ruler 例9.8 在ruler文件中查找包含以“y”开头、“t”结尾、中间是连续1-2个字母“a”的字符串的行,可用
7、如下命令:rootlocalhost temp#grep“ya1,2t”ruler9.2 字符截取命令69.2.1 cut字符提取命令 cut命令的完整路径是/bin,任何用户都有权限执行,其功能是用于提取文件中指定的列。命令格式:rootlocalhost temp#cut-f 列号|-d 分隔符 文件名 选项说明:-f 列号 提取指定的列,若要提取多列,用“,”分割各列。-d 符号 按照指定符号分割列,默认分割符是tab键,分隔符必须是单一的一个字符,如,当以空格作为分隔符时,如果用户不慎输入连续的多个空格符时,只把第一个空格符作为分隔符。所以对于将多个空格符作为字段分隔符的情况,就难于用
8、cut命来提取字段。以下是/temp/cut-studentinfo.txt文件的内容,本节部分实验和例题以该文件为例:IDNAMESEXAGEDEPARTMENT01LiningM18computer02MaolingW20english03YangminM21math04 Wanghong M19physical注意:每条记录的字段之间一定用tab键作为分割。9.2 字符截取命令79.2.1 cut字符提取命令 例9.9 可用如下命令提取cut-studentinfo.txt文件中的姓名(第二列)和年龄(第四列):rootlocalhost temp#cut f 2,4 cut-stude
9、ntinfo.txt 执行结果为:NAMEAGELining18Maoling20Yangmin21Wanghong19 例9.10 可用如下命令提取/etc/passwd文件的第一列和第五列rootlocalhost temp#cut f 1,5 d:/etc/passwd#passwd文件中各列之间用“:”分隔 显示结果:(略)例9.11 可用如下命令提取cut-studentinfo.txt文件中的第三行的第五列:rootlocalhost temp#grep Maoling cut-studentinfo.txt|cut f 5 显示结果:english9.2 字符截取命令89.2.2
10、 格式化输出命令printf printf命令是字符串截取命令awk的标准输出调用命令。printf命令的完整目录是/bin,所有用户都有权限执行,其功能是将指定内容按指定格式输出到屏幕。命令格式:rootlocalhost temp#printf 选项1 选项2 输出内容 选项说明:选项1指定输出类型,各选项功能如下:%ns 输出字符串。n是整数,其绝对值为输出宽度,n0右对齐,n0右对齐,n0右对齐,n19 print$2t$4t$5 执行结果:Maoling 20 englishYangmin 21 math 结果分析:其中,“grep-v NAME”命令把/tmp/temp/cut-s
11、tudentinfo.txt文件的标题行筛选掉了,否则,在执行“awk$419”命令时会报错,因为标题行的第四个字段是“AGE”,不能比较大小。9.2 字符截取命令159.2.3 sed命令 sed命令是一个轻量级的流编辑工具。vi或vim只能编辑文件内容,而不能直接编辑特定命令(如 df-h)的输出结果。sed命令除了主要编辑命令的输出结果外,还可以以命令的方式对文件内容进行操作。在编辑命令的输出结果时,sed命令可以通过管道接收命令的输出。命令格式:rootlocalhost temp#sed 选项 动作 文件名 选项说明:-n 缺省情况下,sed命令把所有数据全部输出到屏幕,该选项输出指
12、定行。-e 允许用多条sed命令对输入数据进行编辑。-i 将sed命令的修改结果直接作用于读取数据的文件,而不是由屏幕输出。动作说明:执行的动作必须要用单引号标记。执行多行时,除了最后一行外,每行结尾添加“”符号,表示数据未结束。a 追加(append),在当前行后添加一个或多个新行。c 行替换,用c后面的字符串替换原数据行。i 插入行(insert),在当前行插入一个或多个新行。d 删除指定行。p 打印输出指定行。s 字符串替换,用一个字符串替换另一个字符串。格式为:“行范围s/旧字符串/新字符串/g”。9.2 字符截取命令169.2.3 sed命令 例9.21 可用如下命令输出cut-st
13、udentinfo.txt文件的标题行(即第一行):rootlocalhost temp#sed-n 1p cut-studentinfo.txt 执行结果为ID NAME SEX AGE DEPARTMENT 结果分析:命令中“1p”表示执行的动作是在屏幕中输出文件的第一行,注意“1”不能省略。选项“-n”表示只输出动作规定的内容,如果缺省,则在输出第一行后,又把整个文件输出一次,如:rootlocalhost temp#sed 1p cut-studentinfo.txt 执行结果为:ID NAME SEX AGE DEPARTMENTID NAME SEX AGE DEPARTMENT0
14、1 Lining M 18 computer02 Maoling W 20 english03 Yangmin M 21 math04 Wanghong M 19 physical sed命令支持管道符输出。9.2 字符截取命令179.2.3 sed命令 例9.22 可用如下命令输出/etc/passwd文件的第三行内容:rootlocalhost temp#cat/etc/passwd|sed-n 3p 执行结果为:daemon:x:2:2:daemon:/sbin:/sbin/nologin 例9.23 可用如下命令将cut-studentinfo.txt文件输出时,删除 第二行和第三行,
15、而不删除文件本身的相关内容:rootlocalhost temp#sed 2,3d cut-studentinfo.txt 执行结果为:ID NAME SEX AGE DEPARTMENT03 Yangmin M 21 math04 Wanghong M 19 physical 注意:标题行是第一行。例9.24 cut-studentinfo.txt文件末尾追加一个新行,内容为:“05ZhangliM18tmath”:rootlocalhost temp#sed 5a 05tZhanglitMt18tmath cut-studentinfo.txt 执行结果为:04 Wanghong M 19
16、 physical05 Zhangli M 18 math 结果分析:上例为在指定行追加新行,如果要在指定行插入新行则用动作参数“i”,如果要使修改作用于文件,则使用“-i”选项,如:9.2 字符截取命令189.2.3 sed命令 例9.25 将cut-studentinfo.txt文件的第五行(第四条记录)替换为“No this student!”:rootlocalhost temp#sed 5c No this student!cut-studentinfo.txt 执行结果为:03 Yangmin M 21 mathNo this student!例9.26 将cut-studenti
17、nfo.txt文件中第五行的“Wanghong”替换为“Wangli”:rootlocalhost temp#sed 5sWanghongWanglig cut-studentinfo.txt 执行结果为:03 Yangmin M 21 math04 Wangli M 19 physical 注意:该命令将把第五行中所有的“Wanghong”替换为“Wangli”。例9.27 可用如下命令将cut-studentinfo.txt文件中所有的“M”替换为“W”,把所有的“18”替换为“20”:rootlocalhost temp#sed-e sMWg;s1820g cut-studentinfo
18、.txt 执行结果为:ID NAWE SEX AGE DEPARTWENT01 Lining W 20 computer02 Waoling W 20 english03 Yangmin W 21 math04 Wanghong W 19 physical 结果分析:命令中使用了“-e”选项,运行sed命令执行多个操作,多个操作之间用“;”分割,动作中没指定行号,表示在全文中执行指定的操作。上述示例中都没有使用选项“-i”,所以所有的操作没有作用到文件本身,只是对文件的输出进行了修改,如果要将修改永久保存到文件,则使用“-i”选项即可。9.3 字符处理命令199.3.1 排序命令 sort命令
19、的功能是将指定文件的内容按某种方式排序。命令格式:rootlocalhost#sort选项 文件名 选项说明:-f 忽略大小写。-n 指定以数值型进行排序,缺省使用字符顺序排序。-r 反向排序。-t 指定分隔符,缺省分隔符是tab制表符。-k n,m:按指定范围的字段排序。从第n字段开始,m字段结束(缺省是行尾)例9.28 可用如下命令对cut-studentinfo.txt文件内容按字符顺序排序:rootlocalhost temp#sort cut-studentinfo.txt 例9.29 对cut-studentinfo.txt文件内容按反向字符顺序排序:rootlocalhost t
20、emp#sort r cut-studentinfo.txt#排序顺序正好与例9.27相反 例9.30 对/etc/passwd文件按每行的第三个字段排序:rootlocalhost temp#sort-n-t:-k3,3/etc/passwd 执行结果为:root:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/
21、nologin 结果分析:命令中的选项“-n”指定按数字类型的值进行排序,默认升序排序,“-t”选项指定分隔符为“:”,“-k3,3”指定按第三个字段排序。9.3 字符处理命令209.3.2 条件统计命令 wc命令用于统计指定文件中的行数、单词数和字符数。命令格式:rootlocalhost temp#wc 选项 文件名 选项说明:-l 只统计行数(line)。-w 只统计单词数(word)。-m 只统计字符数(mark)。例9.31 可用如下命令统计cut-studentinfo.txt文件中的行数、单词数和字符数:rootlocalhost temp#wc cut-studentinfo.
22、txt 执行结果:5 25 122 cut-studentinfo.txt 结果分析:表示cut-studentinfo.txt文件,共有5行25个单词122个字符。如果要只统计文件的行数、单词数或字符数,则使用相应的命令选项则可。9.4 条件判断219.4.1判断特定类型的文件是否存在 判断文件是否存在可以用如下两种命令格式:rootlocalhost temp#test 选项 文件名或rootlocalhost temp#选项 文件名 两种格式功能相同,后者多用于shell脚本编程,其中,最外层的一对方括号是必须的命令符号,且“”的后面和“”的前面必须有空格。选项说明:-b 判断该文件是否
23、为块(block)设备文件且存在,如果是,结果为真。-c 判断该文件是否为字符(character)设备文件且存在,如果是,结果为真。-d 判断该文件是否为目录(directory)文件且存在,如果是,结果为真。-e 判断该文件是否存在(exist),如果是,结果为真。-f 判断该文件是否为普通文件(file)且存在,如果是,结果为真。-z 判断该文件名是否为空,如果是,结果为真。-L 是否为链接(Link)文件且存在,如果是,结果为真。-p 判断该文件是否为管道(pipine)文件且存,如果是,结果为真。-s 判断该文件是否存在并且非空,如果是,结果为真。-S 是否存在并且为套接(Socke
24、t)字文件,如果是,结果为真。例9.32 可用如下命令判断/etc/passwd文件是否存在:rootlocalhost temp#test-e/etc/passwd或rootlocalhost temp#-e/etc/passwd 例9.33 可用如下命令判断/temp目录文件是否存在(该目录的确存在),如果存在输出“yes”,否则输出“no”:rootlocalhost temp#-d/temp&echo yes|echo no 执行结果为:yes9.4 条件判断229.4.2判断文件权限 判断文件权限也可以用如下两种命令格式:rootlocalhost temp#test 选项 文件名或
25、rootlocalhost temp#选项 文件名 该命令只能判断文件是否有读、写或执行权限,而不能精确判定是所有者、所属组还是其他人有相应权限,比如:所有者、所属组或其他人三种用户中只要有一种用户对该文件有读权限,其结果就是真。选项说明:-r 判断指定文件是否存在且有读权限,如果是,结果为真。-w 判断指定文件是否存在且有写权限,如果是,结果为真。-x 判断指定文件是否存在且有执行权限,如果是,结果为真。-u 判断指定文件是否存在且拥有SUID权限,如果是,结果为真。-g 判断指定文件是否存在且拥有SGID权限,如果是,结果为真。-k 判断指定文件是否存在且拥有SBit权限,如果是,结果为真
26、。例9.34 可用如下命令判断cut-studentinfo.txt文件是否有读权限,如果是输出“yes”,否则输出“no”:rootlocalhost temp#-r cut-studentinfo.txt&echo yes|echo no 执行结果为:yes9.4 条件判断239.4.3 文件之前进行比较 文件比较可以用如下两种命令格式:rootlocalhost temp#test文件名1 选项 文件名2 或rootlocalhost temp#文件名1 选项 文件名2 选项说明:-nt 判断文件1和文件2的修改时间,如果文件1的修改时间更接近于当前时间,则结果为真;-ot 判断文件1和
27、文件2的修改时间,如果文件1的修改时间更早于当前时间,则结果为真;-ef 判断文件1和文件2的Inode是否一致,即是否为同一文件,常用于判断是否为硬链接。例9.35 新建cut-studentinfo.txt的硬链接文件studentinfo.txt,验证这两个文件为同一文件 首先,新建cut-studentinfo.txt文件的硬链接文件studentinfo.txtrootlocalhost temp#ln cut-studentinfo.txt zhengze/studentinfo.txt 然后,显示两个文件的Inode:rootlocalhost temp#ls-li cut-st
28、udentinfo.txt ./zhengze/studentinfo.txt 执行结果:261738-rw-r-r-.2 root root 122 Apr 29 04:48 cut-studentinfo.txt261738-rw-r-r-.2 root root 122 Apr 29 04:48./zhengze/studentinfo.txt 由于两个文件的Inode相同,所以是同一文件,验证如下:rootlocalhost temp#test cut-studentinfo.txt-ef./zhengze/studentinfo.txt&echo yes|echo no 执行结果为:
29、yes9.4 条件判断249.4.4 整数比较 比较两个数的大小可用如下两种命令格式:rootlocalhost temp#test整数1 选项 整数2或rootlocalhost temp#整数1 选项 整数2 选项说明:-eq 如果整数1和整数2相等(equal),则结果为真。-ne 如果整数1和整数2不相等(Not equal),则结果为真。-gt 如果整数1大于(greater than)整数2,则结果为真。-lt 如果整数1小于(less than)整数2,则结果为真。-ge 如果整数1大于等于(Greater than or equal)整数2,则结果为真。-le 如果整数1小于等
30、于(Less than or equal)整数2,则结果为真。例9.36 可用如下命令判断两个变量的值是否相等:rootlocalhost temp#var1=2rootlocalhost temp#var2=6rootlocalhost temp#$var1-eq$var2&echo yes|echo no 执行结果:no9.4 条件判断259.4.5 字符串比较 命令格式类似于前述整数比较。选项说明:-z 单目运算,如果字符串为空,则结果为真-n 单目运算,如果字符串不为空,则结果为真。=双目运算,如果两个字符串相等,则结果为真。(注意:运算符两边要有空格)!=双目运算,如果两字符串不相等
31、,则结果为真。(注意:运算符两边要有空格)例9.37 可用如下命令比较两个字符串是否相等:rootlocalhost temp#var_c_1=CentOS#等号的两边不能有任何空格rootlocalhost temp#var_c_2=ubunto#中间无空格的字符串赋值,可以不用引号rootlocalhost temp#$var_c_1=$var_c_2&echo yes|echo no 执行结果为:no 解释说明:判断两个整数是否相等用“-eq”选项,而判断两个字符串是否相等要用“=”选项。9.4 条件判断269.4.6 多重条件判断 命多重条件判断令格式类似于字符串比较:rootloca
32、lhost temp#逻辑表达式1 选项 逻辑表达式2 选项说明:-a 双目运算,如果逻辑表达式1和逻辑表达式2同时成立,则结果为真。-o 双目运算,逻辑表达式1和逻辑表达式2只要有一个成立,则记过为真。!单目运算,逻辑非。例9.38 可用如下命令判断如果var1=3且var2=6,则输出“yes”:rootlocalhost temp#var1=3rootlocalhost temp#var2=6rootlocalhost temp#$var1-eq 3-a$var2-eq 6&echo yes|echo no 输出结果为:yes9.5 流程控制279.5.1 if选择语句1单分支if语句
33、if语句中,如果使用“;”作为分割符时,整个if语句的程序块可以写在一行,其语法格式是:if 逻辑判断式;then 程序体;fi#fi是if语句的结束标志 不使用“;”分割时,then和fi都要另起一行,其语法格式是:if 逻辑判断式then 程序体fi 其中的逻辑表达式是test判断语句(按test命令格式书写),if是语句开始标识符,fi是语句结束标识符,then表示当逻辑表达式的值为真时,执行其后的程序体。例9.39 可用如下命令判断var1的值是否为3,如果是输出“ok!”:rootlocalhost temp#if$var1-eq 3;then echo ok;fi 例9.40 编写
34、shell脚本文件“partition_test.sh”,当/dev/sda1分区使用率达到80%以上后发布预警。rootlocalhost temp#vi partition_test.sh#输入如下内容:#!/bin/bash#Author:Yhrate=$(df-h|grep/dev/sda1|awk print$5|cut-d%-f 1)if$rate-ge 80 then echo warning:Partition sda1 is full!fi 编辑完成后,保存退出,然后执行如下命令:rootlocalhost temp#chmod 755./partition_test.sh
35、rootlocalhost temp#./partition_test.sh 把该脚本与定时任务结合起来,可以完成定时检查分区的任务。Shell编程中,流程控制语句主要包括顺序控制、分支控制和循环控制三类。这里主要介绍后两类流程控制语句。9.5 流程控制289.5.1 if选择语句2两分支if语句 类似于单分支if语句,语法格式为:if 逻辑判断式;then 程序体;else程序体;fiif、then、else和fi各部分也可以不写在同一行,这时要去掉“;”。例9.41 编写shell脚本,完成对cut-studentinfo.txt文件的备份。新建脚本程序:1#!/bin/bash2#Aut
36、hor:Yh3 dt=$(date+%y%m%d)#以年月日格式获取当前时间4 size=$(du-sh/temp/cut-studentinfo.txt)#获取备份文件大小5 if -d/temp/bkp_student#判断/temp/bkp_student是否存在6 then7 echo directory is existent!8 else9 echo The directory unexisted!10 mkdir/temp/bkp_student11 fi12 echo Date:$dt/temp/bkp_student/bkp_student.txt#把备份时间写入文件13 e
37、cho Size:$size/temp/bkp_student/bkp_student.txt#把文件大小写入文件14 cd/temp/bkp_student15#将/temp/cut-studentfinfo.txt和 bkp_student.txt两个文件一起压缩,压缩文件名包含日期信息($dt),压缩产生的所有临时文件全部丢弃(&/dev/null)16 tar-zcf studentinfo_backup_$dt.tar.gz/temp/cut-studentinfo.txt bkp_student.txt&/dev/null 17 rm-fr bkp_stuent.txt#压缩结束后
38、,删除临时文件 可用下面的命令查看压缩包中的文件:rootlocalhost bkp_student#tar-ztvf studentinfo_backup_180430.tar.gz 9.5 流程控制299.5.1 if选择语句3多分支if语句 多分支if语句的语法格式如下:if 逻辑判断式1;then 程序体1;elif 逻辑判断式2;then程序体2;else 程序体n;fi 当然,在多分支语句中,各部分也可以不写在同一行,这时要去掉相应的“;”。例9.42 判断var1的值是否为 1,如果是,则输出“The value of var1 is:1”,否则判断var1的值是否为2,如果是,
39、则输出“The value of var1 is:2”,否则输出“The value of var1 is othes.”。该问题属于多分支选择情况,所以使用if多分支选择语句,编写程序如下:rootlocalhost bkp_student#if$var1-eq 1;then echo The value of var1 is:1;elif$var1-eq 2;then echo The value of var1 is:2;else echo The value of var1 is othes.;fi 执行结果(略)。9.5 流程控制309.5.1 if选择语句3多分支if语句 例9.4
40、3 下面的Shell脚本判断输入文件是否存在,如果不存在,返回,如果存在进一步判断文件的类型:#!/bin/bash#Author:Yh read-p please input a name of file:file#从键盘输入一个文件名赋值给file变量if -z$file#判断文件名是否为空 then echo Warning:the length of the file cant be 0!exit 1#跳出程序并返回数值:1elif !-e$file#判断文件是否存在 then echo Error:the file$file unexisted!exit 2#跳出程序并返回数值:2e
41、lif -f$file then echo$file is a normal file.elif -d$file then echo$file is a derictory.else echo$file is an other file.9.5 流程控制319.5.2 case选择语句 与if语句的多分支结构类似,case语句也是一种多分支选择语句,不同的是if语句可以判断多种不同变量的条件,而case语句只能针对一个变量进行多种情况的判断,即某一特定变量取不同值的情况。语法格式:case$变量名 in值1)程序体1;值2)程序体2;*)程序体n;esac case的各部分也可以写在同一行,注
42、意用分号分割(对于case语句,两种格式都要用双分号分割):case$变量名 in 值1)程序体;值2)程序体;*)程序体;esac 例9.44 可用如下命令语句判断var1变量的值,如果var1=1,则打印“*”,如果var1=2,则打印“*”,如果为其它情况时,打印“*”:rootlocalhost#var1=3rootlocalhost#case$var1 in 1)echo*;2)echo*;*)echo*;esac 执行结果:*9.5 流程控制329.5.3 for循环语句1循环次数不定的for循环结构 这种格式适合循环次数不定的情况,语法格式:for 变量 in 值1 值2 值nd
43、o程序体done 该for语句循环n遍,第一次循环,把值1赋值给变量,第二次循环,把值2赋值给变量,以此类推。如果写在一行,则相应的语法格式为:for 变量 in 值1 值2 值n;do程序体;done 例9.45 写一个shell脚本whatday.sh,要求输出星期日星期六。新建脚本程序:#!/bin/bash#Author:Yhfor Day in Sunday Monday Tuesday Wednesday Thursday Friday Saturday do echo Today is$Daydone 注意:第三行中“Day”变量名前不能用“$”符号,这里不是引用变量而是给变量赋
44、值。9.5 流程控制339.5.3 for循环语句1循环次数不定的for循环结构 例9.46 编写shell脚本文件unzip_batch.sh,批量解压/temp目录下所有以tar.gz为后缀的压缩文件。新建unzip_batch.sh脚本程序:#!/bin/bash#Author:Yhcd/templs*.tar.gz ls.txt#显示以tar.gz为后缀所有文件,并输出重定向到ls.txt文件for file in$(cat ls.txt)#注意“$”、“()”两个符号必须要有 do echo The filename is:$file tar-zxf$file&/dev/null#逐
45、个解压文件done2循环次数确定的for循环结构 这种格式适合循环次数确定的情况。语法格式:for(赋初始值;循环控制条件;改变控制变量)do程序体Done 例9.47 编写shell脚本sum.sh,求1+2+3+100的值。新建sum.sh脚本程序:#!/bin/bash#Author:Yhsum=0for(i=1;i101;i=i+1)do sum=$(sum+i)#可以写为:sum=$($sum+i)doneecho The sum is:$sum9.5 流程控制349.5.3 for循环语句2循环次数确定的for循环结构 例9.48 编写shell脚本useradd_batch.sh
46、,批量增加系统用户。新建useradd_batch.sh脚本程序:#!/bin/bash#Author:Yhread-p please input username:-t 30 userread-p please input passward:-t 30 passread-p please input number of users:-t 30 num#三个值只要有一个输入为空,就进行警告,并令程序强行返回if -z$user|-z$pass|-z$num then echo Warning:usernamepasswardnumber of users cant be blank!exit
47、1fi#如果用户数量不是数字类型,则强制程序返回 y=$(echo$num|sed s/0-9/g)if !-z$y then echo Please enter the correct value for the number of users!exit 2 fi#循环添加指定数量的用户 for(i=1;i/dev/null echo$pass|/usr/bin/passwd-stdin$user$i&/dev/null done echo The user has been successfully added!9.5 流程控制359.5.3 for循环语句2循环次数确定的for循环结构
48、运行该脚本,依次输入:user、yhao、5,程序运行完后执行以下命令:rootlocalhost temp#cat/etc/passwd 执行结果:user1:x:500:500:/home/user1:/bin/bashuser2:x:501:501:/home/user2:/bin/bashuser3:x:502:502:/home/user3:/bin/bashuser4:x:503:503:/home/user4:/bin/bashuser5:x:504:504:/home/user5:/bin/bash 表明已经添加了5个用户。结果解释:语句“if -z$user|-z$pass|
49、-z$num”不能用“if -z$user r-z$pass -r-z$num”替换,否则会报错!语句“echo$pass|/usr/bin/passwd-stdin$user$i”的解释:修改用户$user$i的密码,-stdin指接收echo的管道输出作为密码。9.5 流程控制369.5.4 while循环语句 while语句也是一种循环控制语句。语法格式:while 循环条件 do 循环体;done 注意:关键词while后面“”的后面和“”的前面必须要有空格符。echo 1+2+3+.+100=$sum 例9.49 编写shell脚本sum_while.sh,求1+2+100的值。新建
50、sum_while.sh脚本程序:#!/bin/bashi=1sum=0while$i-le 100 do sum=$($sum+$i)i=$($i+1)echo 第$i个数是$sumdone9.5 流程控制379.5.5 until循环语句 while循环语句中,循环体的执行条件是:只要循环条件成立,就一直执行,直到循环条件不成立,而until语句中,循环体的执行条件是:只要循环条件不满足,则一直执行,直到循环条件得到满足。语法格式:until 循环条件 do 循环体;done 同样,关键词until后面“”的后面和“”的前面必须要有空格符。用until语句改写 例9.48,实现同样功能:#