shell 12 --- 循环控制及状态返回值(break、continue、exit、return)
本文介绍几个特殊的命令:
break(循环控制)、continue(循环控制)、exit(退出脚本)、return(退出函数)。
12.1 break、continue、exit、return的区别和对比
在上述命令中,break、continue在条件语句及循环语句(for、while、if等)中用于控制程序的走向;
而exit则用于终止所有语句并退出当前脚本,除此之外,exit还可以返回上一次程序或命令的执行状态值给当前Shell;
return类似于exit,只不过return仅用于在函数内部返回函数执行的状态值。
关于这几个命令的基本说明如表12-1所示。
命令 | 说明 |
---|---|
break n | 如果省略n,则表示跳出整个循环,n便是跳出循环的层数 |
continue n | 如果省略n,则表示跳过本次循环,忽略本次循环的剩余代码 进入循环的提一次循环。n表示退到第几层继续循环 |
exit n | 退出当前shell程序,n为上一次程序执行的状态返回值。 n也可以省略,在下一个shell例可通过"$?"接收exit n的返回值 |
return n | 用于在函数里作为函数的返回值,以判断函数执行是否正确。 在下一个shell里可通过"$?"接收return n的值 |
12.2 break、continue、exit功能执行流程图
为了更清晰地了解上述命令的区别,下面特别画了逻辑图,方便大家理解。
这里以while循环和for循环为例来说明。
12.2.1 break功能的执行流程逻辑图
在循环中break功能的执行流程逻辑图如图12-1所示。
12.2.2 continue功能的执行流程逻辑图
在循环中continue功能的执行流程逻辑图如图12-2所示。
12.2.3 exit功能的执行流程逻辑图
在循环中exit功能的执行流程逻辑图如图12-3所示。
12.3 break、continue、exit、return命令的基础示例
下面是与break、continue、exit、return相关的示例。
[root@zabbix 0513]# cat test.sh
#!/bin/bash
if [ $# -ne 1 ];then
echo $"usage: $0 {break|continue|exit|return}"
exit 1
fi
function test(){
for((i=0;i<=5;i++))
do
if [ $i -eq 3 ];then
$*;
fi
echo $i
done
echo "I am in func"
}
test $*
func_ret=$?
if [ `echo $*|grep return|wc -l` -eq 1 ];then
echo "return‘s exit status: $func_ret"
fi
echo "OK"
12.3.1 break功能测试说明
传入break执行结果:
[root@zabbix 0513]# sh test.sh break
0
1
2
I am in func === 传入break时,退出test函数,继续顺序执行test函数以下的
OK
说明:
根据结果可以看到,i等于3及以后的循环没有被执行,但循环外的echo执行了,
执行到break时跳出了if及外层的for循环语句,然后执行for循环外部done后面的打印ok的语句。
12.3.2 continue功能测试说明
[root@zabbix 0513]# sh test.sh continue
0
1
2 ===下面没有3,直接跳过了
4
5
I am in func
OK
说明:
可以看到,只有i等于3这层循环没有被执行,其他循环全部执行了,
循环外的echo也执行了,说明执行到continue时,终止了本次循环,
而继续下一次的循环,直到循环正常结束,接着继续执行了循环外面的所有语句。
12.3.3 exit功能测试说明
传入exit 119命令的执行结果为:
[root@zabbix 0513]# sh break.sh "exit 119"
0
1
2 === 直接退出shell
[root@zabbix 0513]# echo $?
119 === 返回了119,即传入的值
说明:
当进入循环里的if语句后遇到"exit 119"时,立刻退出程序,不但循环体3后面的数字没有输出,
而且for循环体done外的echo和函数外的ok也没有输出,就直接退出了程序。
另外,因为程序退出时指定了119, 所以执行脚本后获取"$?"的返回值时,
就返回了"exit 119"后面的119这个数字到当前的Shell。
12.3.4 return功能测试说明
传入"return 119"命令的执行结果为:
[root@zabbix 0513]# sh break.sh "return 119"
0
1
2
return‘s exit status: 119
OK
说明:
当进入循环里的if语句后遇到return 119,就没有打印3以下的数字,
说明return跳出了循环体,程序也没有执行for循环体done外的echo命令,
而是直接执行了函数test外的if语句及打印ok的命令,可见return的作用是退出当前函数。
同时,return将数字119作为函数的执行状态值返还给函数体外,
执行脚本后打印返回值是0,因为程序的最后一行是打印ok的命令,执行是成功的。
12.4 循环控制及状态返回值企业案例
范例12-2:开发Shell脚本实现为服务器临时配置多个IP,并且可以随时撤销配置的所有IP。
IP的地址范围为:10.0.2.1~10.0.2.16,其中10.0.2.10不能配置。
本题主要用于考察continue、return、exit的综合应用,请读者细细品味。
首先,给网卡配置额外的IP。以下介绍两种配置IP的命令(ifconfig/ip)。
12.4.1 临时配置多个ip的方法
1)使用ifconfig配置别名IP的方法:
ifconfig eth0:0 10.0.0.10/24 up ==> 添加ip
ifconfig eth0:0 10.0.0.10/24 down ==> 删除ip
2)使用IP配置辅助IP的方法:
ip addr add 10.0.0.12 dev eth0 lable eth0:0
ip addr del 10.0.0.12 dev eth0 lable eth0:0
3)然后批量配置IP。
要求IP地址的取值范围为:10.0.2.1~10.0.2.16,其中10.0.2.10不能配置。
for ip in {1..16}
do
if [ $ip -eq 10 ];then
continue
else
ifconfig ens33:$ip 10.0.0.${ip}/24 up
fi
done
4)shell 脚本实现
[root@zabbix 0513]# cat add_ip.sh
#!/bin/bash
[ -f /etc/init.d/functions ]&& . /etc/init.d/functions
RETVAL=0
function operation(){
if [ "$1" == "del" ];then
list=`echo {16..1}`
else
list=`echo {1..16}`
fi
for ip in $list
do
if [ $ip -eq 10 ];then
continue
fi
ip addr $1 10.0.0.${ip}/24 dev eth0 lable eth0:$ip &>/dev/null
RETVAL=$?
if [ $RETVAL -eq 0 ];then
action "$1 $ip" /bin/true
else
action "$1 $ip" /bin/false
fi
done
return $RETVAL
}
case "$1" in
start)
operation add
RETVAL=$?
;;
stop)
operation del
RETVAL=$?
;;
restart)
operation del
sleep 2
operation add
RETVAL=$?
;;
*)
printf $"USAGE: $0 {start|stop|restart}"
esac
exit $RETVAL
12.4.2 RANDOM随机数md5比对
范例12-4:
已知下面的字符串是通过将RANDOM随机数采用md5sum加密后任意取出连续10位的结果,
请破解这些字符串对应的md5sum前的数字?
解题思路:本题原本是想考察break的用法,但是还考察了RANDOM随机数的范围,
该范围是0~32767,请务必记住。要想解决本题,首先要将0~32767范围内的所有数字通过md5sum加密,
并把加密后的字符串和加密前的数字对应地写到日志里。然后将题中给出的加密后的字符串4fe8bf20ed和指纹库里的所有使用md5sum加密后的字符串
进行比对(grep最佳),如果匹配,则把对应的行及对应的数字输出。
首先将0~32767范围内的所有数字通过md5sum加密,
并把加密后的字符串和加密前的数字对应地写到日志里,实现脚本如下:
[root@zabbix 0514]# cat random.sh
#!/bin/bash
for n in {0..327767}
do
echo "`echo $n|md5sum` $n" >>/tmp/finger.txt
done
# [root@zabbix 0514]# grep -w 722 /tmp/finger.txt
# f136b51b96a2a2ccefab9b82f1182d91 - 722
md5char="f136b51b96a2a2ccefab9b82f1182d91"
while read line
do
if [ `echo $line|grep "$md5char" |wc -l` -eq 1 ];then
echo $line
break
fi
done < /tmp/finger.txt
[root@zabbix 0514]# sh random.sh
f136b51b96a2a2ccefab9b82f1182d91 - 722