shell脚本-循环、case语句,函数及中断控制
2019-04-10 00:09
881 查看
简介
循环
- for循环
在Shell脚本应用中,常见的for循环采用遍历式、列表式的执行流程,通过指定变量从值列表中循环赋值,每次复制后执行固定的一组操作。
- 语法结构
for 变量名 in 值列表 #可以是数值、字母,以空格隔开 do 命令序列 done for 变量名 in {1..5} #{起始值~末尾值}==>1 2 3 4 5 do 命令序列 done for 变量名 in `seq 5` #用于以指定增量从首数开始打印数字到尾数,即产生从某个数到另外一个数之间的所有整数 do 命令序列 done for 变量名 in `ls /etc/*.conf` #读取文件内容 do 命令序列 done
- 例子1 利用循环打印出reve
#A: #!/bin/bash #循环打印出reve a=10 for i in 1 2 3 do echo "reve" done ----------------------------------------------- [root@reve shell]# bash test.sh #A: 结果 reve reve reve #B: #!/bin/bash #循环打印出reve a=10 for i in {1..3} do echo "reve" done ----------------------------------------------- [root@reve shell]# bash test.sh #B: 结果 reve reve reve ------------------------------------------------ #C: #!/bin/bash #循环打印出reve a=10 for i in `seq $a` #seq命令用于以指定增量从首数开始打印数字到尾数,即产生从某个数到另外一个数之间的所有整数,并且可以对整数的格式、宽度、分割符号进行控制, #在这里的 `seq $a` 表示:1 2 3 4 5 do echo "reve" done [root@reve shell]# bash test.sh #C: 结果 reve reve reve reve reve reve reve reve reve reve ---------------------------------------------
- C语言风格的for循环格式 通过变量控制,条件成立循环
- 步长可以控制
for((初值;条件;步长控制)) do 命令序列 done
- 例子2利用循环ping 一个网段,有多少台主机可以ping通
注意ping命令可以测试某台主机的连通性,
使用-c选项可以设置ping的次数,
使用-i选项可以设置多次ping之间的间隔时间(单位秒),
使用-W选项可以设置ping不通时的超时时间(单位秒)。
#!/bin/bash #利用循环ping 一个网段,有多少台主机可以ping通 for i in {40..50} #由于我的主机的IP是49,所以我就缩小范围,节省时间。 do ping -c 3 -i 0.2 -W 1 192.168.4.$i &> /dev/null #输出结果给丢弃掉 if [ $? -eq 0 ];then #判断上一条语句的是否ping通,通就说明,执行成功,#? 返回 0.反之$? 返回 1 echo " 192.168.4.$i 通了" let a++ #通了,就子增 + 1 else echo " 192.168.4.$i 不通" let b++ #不通也自增 + 1 fi done echo "有$a 台主机通了" #统计最后的结果 echo "有$b 台主机不通" --------------------------------------------------- [root@reve shell]# vim Ping_color.sh [root@reve shell]# bash Ping_color.sh 192.168.4.45 不通 192.168.4.46 不通 192.168.4.47 不通 192.168.4.48 不通 192.168.4.49 通了 192.168.4.50 不通 有1 台主机通了 有5 台主机不通 [root@reve shell]# vim Ping_color.sh [root@reve shell]# bash Ping_color.sh 192.168.4.45 不通 192.168.4.46 不通 192.168.4.47 不通 192.168.4.48 不通 192.168.4.49 通了 192.168.4.50 不通 有1 台主机通了 有5 台主机不通
- 例子3一次性创建10个账户
#!/bin/bash #一次性创建10个账户 for i in {1..10} do useradd user$i done ---------------------------- [root@reve shell]# bash Create_user.sh #创建用户成功,是不会有提示信息的 [root@reve shell]# bash Create_user.sh useradd:用户“user1”已存在 useradd:用户“user2”已存在 useradd:用户“user3”已存在 useradd:用户“user4”已存在 useradd:用户“user5”已存在 useradd:用户“user6”已存在 useradd:用户“user7”已存在 useradd:用户“user8”已存在 useradd:用户“user9”已存在 useradd:用户“user10”已存在 #但是这个脚本存在一些问题,用户名写死了,不符合实际情况 ----------------------------- #我们可以让for循环读取文件的内容,例如读取员工信息表。按照里面的名字来创建名字 [root@reve shell]# cat /root/user #创建这份文件,文件内容是用户名 zhangsan lisi wangwu reve dingren #!/bin/bash #读取文件中的用户名,创建用户 for i in `cat /root/user` #让for循环读取这份文件 do useradd $i done --------------------------------------- [root@reve shell]# bash Create_user.sh [root@reve shell]# bash Create_user.sh useradd:用户“zhangsan”已存在 useradd:用户“lisi”已存在 useradd:用户“wangwu”已存在 useradd:用户“reve”已存在 useradd:用户“dingren”已存在 [root@reve shell]# vim Create_user.sh
- while 循环
while循环属于条件式的执行流程,会反复判断指定的测试条件,只要条件成立即执行固定的一组操作,直到条件变化为不成立为止。所以while循环的条件一般通过变量来进行控制,在循环体内对变量值做相应改变,以便在适当的时候退出,避免陷入死循环。
- 语法结构
while 条件测试 #没有冒号 “ : ” 但是有空格 do 命令序列 done while : #有空格 do 命令序列 done
- while死循环:
#!/bin/bash whlie : #条件永远成立 ==死循环 do echo "abc" done
执行这样的脚本和会让机器陷入死循环,会消耗大量的CPU资源,如下图片。 我用一台虚拟机执行这样程序,这里可以看到我的一个CPU资源已经达到了100%。这样长期执行这样的脚本,会对机器造成很大影响。所以我们在执行while循环,需注意避免进入这样的死循环。
- 例子4利用while循环猜一个随机生成的数字
#!/bin/bash #利用while循环猜一个数字 Num=$[RANDOM% 100 + 1] #随即生成一个数,这个值不参与while循环当中。 b=0 while : do let b++ #需要提前对b进行初始化复为0 read -p "请输入一个数字(1~100):" a #从键盘上读取一个值 if [ $a -eq $Num ];then echo "你猜对了,总计:猜了$b次" exit 2 #猜对了就退出,避免进入死循环 elif [ $a -gt $Num ];then echo "你猜大了" else echo "你猜小了" fi done
- 例子5 检测某一网段,列出不在线的主机地址
#!/bin/bash i=1 while [ $i -le 254 ] # <= 254 do IP="192.168.4.$i" ping -c 3 -i 0.2 -W 1 $IP &> /dev/null if [ $? -eq 0 ] ; then echo "Host $IP is up." else echo "Host $IP is down." fi let i++ done
分支
Case语句case分支节结构语法结构执行流程Demo- case分支:与if类似,可以说是if的简化版本
case分支属于匹配执行的方式,它针对指定的变量预先设置一个可能的取值,判断该变量的实际取值是否与预设的某一个值相匹配,如果匹配上了,就执行相应的一组操作,如果没有任何值能够匹配,就执行预先设置的默认操作。
- 语法结构:
case 变量 in 模式1) #同时模式1)后面有个“)” 命令序列1 ;; #需要注意:格式必须是两个分号 模式2) 命令序列2 ;; .. .. *) # * 表示默认匹配 默认命令序列 esac
- 例子6 完成一个简化命令的脚本,如:touch : t;
#!/bin/bash #测试case case $1 in #位置变量$1和下面的字符进行匹配,并执行对应的序列 t) touch $2 ;; # $2 输入我们创建的文件名 v) touch $2 ;; c) touch $2 ;; *) echo "t|v|c" esac --------------------------------------- #拓展:我们可以利用管道 | 来实现区分大小写的功能。或者误操作情况。可以自定义: case $1 in #位置变量$1和下面的字符进行匹配,并执行对应的序列 t|T|tt) touch $2 ;; # $2 输入我们要 v) touch $2 ;; c|C) #匹配大写C和小写C都可以执行下面的命令序列 touch $2 ;; *) echo "t|v|c" esac ------------------------------ #测试结果 [root@reve shell]# bash case_test.sh t /opt/case_test [root@reve shell]# bash case_test.sh t /opt/case_test
函数
什么是函数:
- 在shell环境中,将一些需要重复性的操作,定义为公共的语句块,即可称为函数
使用函数的好处
- 使脚本代码更加简洁,增强易读性
- 提高shell脚本的执行效率
服务脚本中的函数应用
-适用与比较复杂的启动/终止控制哦操作
-方便在需要时多次调用
- 函数定义的格式:
#格式1: function 函数名 { 命令序列 .. .. } --------------------------------- 格式2:类似C语言风格 函数名() { 命令序列 .. .. }
- 那我们来写一个函数来试试吧
[root@reve shell]# A(){ > mkdir bbbb > touch aaaa.txt > } [root@reve shell]# type A #type(用来显示指定命令的类型) 可以查看A是否为函数 A 是函数 A () { mkdir bbbb; touch aaaa.txt } [root@reve shell]# type B -bash: type: B: 未找到 [root@reve shell]# A [root@reve shell]# ls bbbb aaaa.txt [root@reve shell]# #注意:我们一般写函数,不写在终端,一般写在shell脚本当中。
- 修改字体颜色:
[root@reve shell]# echo -e "\033[033mABC\033[0m" #修改字体颜色 ABC #橙色 [root@reve shell]# echo -e "\033[024mABC\033[0m" ABC #蓝色 #注意!!!:echo -e(必须带-e); \033[ :是固定格式。 # !!修改字体颜色后,的还原初始化颜色转态,以免造成麻烦。 # !!\033[0m : 还原初始化颜色
- 举例7 书写一个能够修改字体颜色的函数
#!/bin/bash #一个修改字体颜色的函数 Change_color(){ echo -e "\033[$1m$2\033[0m" } Change_color 31 REVE Change_color 32 REVE Change_color 33 REVE Change_color 34 REVE Change_color 35 REVE Change_color 36 REVE Change_color 37 REVE Change_color 38 REVE ------------------------------------- #结果 [root@reve shell]# vim Change_color.sh [root@reve shell]# bash Change_color.sh REVE #红色 REVE #绿色 REVE #橙色 REVE #蓝色 REVE #粉色 REVE #浅蓝色 REVE #灰色 REVE #黑色 [root@reve shell]#
- 拓展测试某一个网段的IP地址,通了显示绿色,不同显示红色
我们可以利用我们刚才的代码,来实现
[root@reve shell]# vim Ping_color.sh #!/bin/bash #利用循环ping 一个网段,有多少台主机可以ping通 Change_color(){ echo -e "\033[$1m$2\033[0m" } for i in {45..50} #由于我的主机的IP是49,所以我就缩小范围,节省时间。 do ping -c 3 -i 0.2 -W 1 192.168.4.$i &> /dev/null #输出结果给丢弃掉 if [ $? -eq 0 ];then #判断上一条语句的是否ping通,通就说明,执行成功,#? 返回 0.反之$? 返回 1问题 Change_color 32 " 192.168.4.$i 通了" let a++ #通了,就子增 + 1 else Change_color 31 " 192.168.4.$i 不通" let b++ #不通也自增 + 1 fi done echo "有$a 台主机通了" #统计最后的结果 echo "有$b 台主机不通"
测试结果
[root@reve shell]# bash Ping_color.sh 192.168.4.45 不通 #红色 192.168.4.46 不通 #红色 192.168.4.47 不通 #红色 192.168.4.48 不通 #红色 192.168.4.49 通了 #绿色 192.168.4.50 不通 #绿色 有1 台主机通了 有5 台主机不通
- shell版本fork炸弹 仅13个字符:.(){.|.&};.
- 递归死循环,可迅速耗尽系统资源
.(){ #定义一个名为 . 的函数 .|.& #在后台递归调用函数 } . #再次调用函数 #注意:此操作非常危险,尽量在虚拟上使用。 #执行此脚本后,可以通过强制关机重启,即可恢复
中断退出
通过break、continue、exit在Shell脚本中实现中断与退出的功能。
类型 | 作用 |
---|---|
break(中断) | 可以结束整个循环 |
continue(继续) | 结束本次循环,进入下一次循环 |
exit (退出) | 结束整个脚本 |
- 例子8:测试这三个中断的效果
#continue #!/bin/bash for i in {1..6} do [$i -eq 4 ] && continue #当循环到4的时候,退出本次循环,继续下次循环 echo $i done echo hahaha -------------------------- #效果 [root@reve shell]# bash Test_contiune.sh 1 2 3 5 6 hahaha ------------------------------- #break #!/bin/bash for i in {1..6} do [$i -eq 4 ] && break #当循环到4的时候,退出本次循环 echo $i done echo hahaha -------------------------- #效果 [root@reve shell]# bash Test_contiune.sh 1 2 3 hahaha [root@reve shell]# --------------------------- #exit #!/bin/bash for i in {1..6} do [$i -eq 4 ] && exit #当循环到4的时候,退出程序 echo $i done echo hahaha -------------------------- [root@reve shell]# bash Test_contiune.sh 1 2 3 [root@reve shell]#
- 例子9:把用户每次输入的值进行求和,输入0则结束
#!/bin/bash #把用户输入的值进行求和,输入0则结束 sum=0 while : #利用while进行循环 do read -p "请输入一组合数字,0结束" Num [ $Num -eq 0 ] && break #把0作为判断条件 sum=$[Num + sum] done echo $sum ---------------------- #结果 [root@reve shell]# bash While_sum.sh 请输入一组合数字,0结束5 请输入一组合数字,0结束5 请输入一组合数字,0结束5 请输入一组合数字,0结束5 请输入一组合数字,0结束0 20
- 例子10:找出1~20以内6的倍数,并输出她的平方值
#!/bin/bash #找出1~20以内6的倍数,并输出她的平方值 sum=0 Num=0 for i in {1..20} do Num=$[i % 6] if [ $Num -eq 0 ];then sum=$[i*i] echo "6的倍数平方值为 $sum " fi done ---------------------- #结果 [root@reve shell]# bash six_sqrt.sh 6的倍数平方值为 36 6的倍数平方值为 144 6的倍数平方值为 324
总结
- 小结
- 循环 for循环,语法格式、C语言风格、长度控制
- while循环、语法格式,死循环问题、
- case 分支 语法结构、管道的用法(大小写的匹配: T|t|tt)、
- 函数 函数定义、函数使用、shell的炸弹、
- 中断 中断类型:contine、exit、break,作用和区别
- 补充 修改字体颜色,大小写匹配
- 常见问题
#for 故障错误信息 #基本语法错误, #for循环的执行,需要嵌入到do和doe中间 #使用case语句时,需要记住后面是以 ;; 结尾的
写的不好,请大家见谅哈
相关文章推荐
- 运维之shell篇-----3.循环结构 、 case语句 、 函数及中断控制
- 循环结构 、 函数及中断控制 、 case语句
- 循环结构 case语句 、 函数及中断控制
- Shell脚本的基本语法(二) 预定义特殊字符、case语句和函数调用
- shell脚本中case条件控制语句的一个bug分析
- Shell脚本的条件控制和循环语句
- SHELLcase流程控制和for、while循环语句的使用
- Shell脚本的条件控制和循环语句
- Shell脚本入门(八) - 循环控制语句: while
- Shell脚本之for、while循环语句和case分支语句
- shell脚本编程之循环控制语句(continue/break/sleep)
- shell脚本中case条件控制语句的一个bug分析
- 04- Shell脚本学习--条件控制和循环语句
- Shell脚本的条件控制和循环语句
- Shell脚本入门(九) - 循环控制语句:for in
- Shell脚本入门(七) - 条件控制语句: case
- Shell 脚本之循环语句(for,while,until)以及case,select,break,continue实例详解
- shell判断、循环、控制语句与函数应用
- 3、shellwhile循环,C-for循环,until循环,case分支结构,流程控制语句
- 学习笔记 shell流程控制语句 while条件循环语句和case条件测试语句