shell脚本编写 之 条件选择,条件判断,循环语句
1 概述 编写shell脚本,一般离不开条件选择,条件判断以及循环语句。掌握这三个语法,将大大提高脚本的编写效率,使得脚本编写更加灵活,完成X相对复杂的工作 2 条件选择if语句 if语句选择执行,逐条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句 if是根据判读条件的命令的退出状态来执行命令,if语句可嵌套 单分支 if判断条件;then 条件为真的分支代码 fi 双分支 if判断条件;then 条件为真的分支代码 else 条件为假的分支代码 fi 多分支 if判断条件1;then 条件为真的分支代码 elif判断条件2;then 条件为真的分支代码 elif判断条件3;then 条件为真的分支代码 else 以上条件都为假的分支代码 fi 例子 比较数字大小结果真假判断 read-p"Pleaseinputnu:"nu [[$nu=~^[0-9]+$]]||{echo"Yourinputisnotnum";exit8;} if["$nu"-gt90];then echo"$nuisbiggerthan90" elif["$nu"-lt50];then echo"$nuislessthan50" else echo"Yourinput$nuisbetweenrange50-90" fi 执行命令结果真假判断 read-p"pleaseinputip:"ip ifping-c1-W1$ip&>/dev/null;then echo"$ipisup" elifgrep"$ip"/root/list&>/dev/null then echo"host"$ip"isundermaitenance" elseecho"$ipisunexpectedlydown,pleasecheck" fi 3 条件判断:case语句 语法如下 case变量引用($var,注意有$符号引用)in PAT1) 分支1 ;; PAT2) 分支2 ;; ...... *) 默认分支 ;; esac 这里的分支x可以是命令的组合,不是单纯的一条命令 case支持glob风格的通配符: *: 任意长度任意字符 ?: 任意单个字符 []:指定范围内的任意单个字符 a|b: a或b,当匹配到不同的字符,但是要执行相同的分支命令是,可以用这个命令简化判断 例子 #!/bin/bash read-p"Pleaseinputyourchoice:"choice final=`echo"$choice"|tr[[:upper:]][[:lower:]]` case$finalin y|yes) echo"Youinput"$choice",andyourchoiceisyes" ;; n|no) echo"Youinput"$choice",andyourchoiceisno"; ;; y???es) echo"Youinput$choice,ithasthreecharacterbetweenyes" ;; [sunny]) echo"Youinput$choice,itonlyhasonecharacter" ;; *) echo"Yourchoiceis$choice,itisnottheanswer" ;; esac 截图如下 4 循环语句 将某代码段重复运行多次,以下三个关键字for,while,until各自的语法构成不同的循环语句 其中 for默认将列表的值依次执行完成后退出 while和until有进入条件和退出条件 重复运行的次数有两类 a.循环次数事先已知 b.循环次数事先未知 4.1 for 循环 4.1.1 for 常规的列表循环 语法如下: for变量名(如var,不需要加$引用变量值)in列表;do 循环体(命令组合) done for循环执行机制: 依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体; 直到列表中的元素耗尽,循环结束 for循环 列表 生成方式: (1) 直接给出列表 (2) 整数列表: (a) {start..end} (b) $(seq[start [step]] end) (3) 返回列表的命令:$(COMMAND) 可以表达为`COMMAND`,反向单引号引起来 (4) 使用glob,如:*.sh (5) 变量引用;$@,$* 4.1.2 例子: 4.1.2.1 直接给出列表型 i=1 forvarinabcd do echo"$icyclethevaris$var" leti++ done 4.1.2.2 整数列表:{start..end..step}型 如果不指定步进值(step),那么默认是步进1 i=1 forvarin{3..15..2} do echo"$icyclethevaris$var" leti++ done 4.1.2.3 整数列表:$(seq[start [step]] end) 型 #如果是 seq end 从1开始递增到end,每次增加1 #如果是 seq start end 从start开始递增到end,每次递增1 #如果是 seq[start] [step] [end] 从start开始,每次递增step,直到end i=1 forvarin$(seq329) do echo"$icyclethevaris$var" leti++ done 4.1.2.4 返回列表的命令 $(COMMAND)型 forvarin$(ls/root/) do echo"$ifileis"$var",typeis`file/root/$var`" leti++ done echo 4.1.2.5 使用glob,如:*.sh或/root/* 型 forvarin/root/* do echo"$ifileis"$var",typeis`file$var`" leti++ done echo 4.1.2.6 变量引用;$@,$*型 forvarin$@ do echo"$icycle,andnowparais$1,varis$var,$@is$@" leti++ shift done echo 4.1.3 for循环的特殊格式: 语法如下 for((控制变量初始化;条件判断表达式;控制变量的修正表达式)) do 循环体 done 控制变量初始化:仅在运行到循环代码段时执行一次 控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断 双小括号方法,即((…))格式,也可以用于算术运算 双小括号方法也可以使bash Shell实现C语言风格的变量操作,如((I++)) 该for循环的执行过程如下 进入循环的时候,先不判断真假,直接执行 控制变量初始化 然后执行 条件判断表达式 ,会判断真假 ,条件为真,开始进入循环 执行循环 执行完循环后 执行 控制变量的修正表达式 然后条件判断表达式 然后条件判断表达式, 。。。。。。。 直到不满足条件判断表达式这个条件后退出循环 逻辑图如下 例子 read-p"Pleaseinputyournutocal1+2+...+nu:"nu s=0 for((i=1;i<=$nu;i=i+1)) do s=$(($s+$i)) echo"itisthe$icycle." done echo"1+2...+$nu=$s" 以上脚本通过调试 bash -x 结果截图如下 4.2 while循环 4.2.1 语法 whileCONDITION(条件判断);do 循环体 done CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断; 条件为“true”,则执行一次循环;直到条件测试状态为“false”终止循环 因此:CONDTION一般应该有循环控制变量;而此变量的值会在循环体不断地被修正 进入条件:CONDITION为true 退出条件:CONDITION为false 4.2.2 while循环的特殊用法: 4.2.2.1 读入文件 whilereadline;do//注意,这里的line只是变量,可以自己命名 循环体 done</PATH/FROM/SOMEFILE 依次读取/PATH/FROM/SOMEFILE这个文件中的每一行,且将行赋值给变量line,每次读入一行进入循环,进行相应的处理 4.2.2.2 将结果传入while 将命令的结果传给while,用管道来传,每次读入命令结果得到一行 命令|whileread变量do 循环体 其中管道命令只能处理标准输出,所以要确保命令有标准输出 done 4.2.2.3 创建无限循环 whiletrue;do 循环体 done 4.2.3例子 4.2.3.1 普通循环 九九乘法表 i=1 while["$i"-lt10];do for((j=1;j<="$i";j++))do echo-e-n"$i*$j=$[$i*$j]t" done echo leti++ done 4.2.3.2 读入文档内容 while 每一次会把输入的文档/root/tt的每一行输入进行处理,等这行完成处理后, 再输入文档的下一行,直到所有的循环都结束 i=1 whilereadline;do echo"$icycleis$lineis<$line>" leti++ echo"$line"|grepgt echo"$line"|sed-nr's/useage=.*/fortestsed/p' echo done</root/tt 4.2.3.3 管道输入 以下命令将 df|grep /dev/sd 的结果通过管道一行一行传入给到变量line。然后进入循环做处理 df|grep/dev/sd|whilereadline;do dev=`echo"$line"|cut-d""-f1` use=`echo"$line"|sed-r's/.*([0-9]+)%.*/1/'` if["$use"-gt3];then echo"Warning"$dev"'susageisover3%,itis$use,pleasecheck" else echo""$dev"'susageissafe,itis$use" fi done 4.2.3.4 创建循环体 每个两秒打印hello whiletrue;do echohello sleep2 done 4.3 until 4.3.1 语法 untilCONDITION;do 循环体 done 进入条件:CONDITION 为false 退出条件:CONDITION 为true until就是和while相反,一般可以用until实现的循环,都可以用while来实现,所以until可以了解一下即可。 创建无限循环 untilfalse;do 循环体 Done 4.3.2 例子 4.3.2.1 until普通循环 当i大于6的时候进入循环,小于或者等于6的时候退出循环 i=10 until[$i-le6];do echo$iis$i,biggerthan6 leti-- echo"afteri--,nowiis$i" echo done 4.3.2.2 无效循环的脚本 打印it is false,然后睡2秒 untilfalse;do echo"itisfalse" sleep2 done 5 小结 使用什么语法进行循环,或者是条件选择或者条件判断,都要根据具体情况来定,同时也是根据个人写脚本的习惯而定,比如有些人就喜欢用while来写循环语句,但是有一个原则就是,尽量把算法定好,防止多次的循环,占用大量的资源,对系统造成负担。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |