流程控制
本章则带领大家学习几个特殊的命令:break(循环控制)、continue(循环控制)、exit(退出脚本)、return(退出函数)
区别和对比
在上述命令中,break、continue在条件语句及循环语句(for、while、if等)中用于控制程序的走向;而exit用于终止所有语句并退出当前脚本。除此之外,exit还可以返回上一次程序或命令的执行状态给当前Shell;return类似于exit,只不过return仅用于在函数内部,如下图所示
命令 | 说明 |
---|---|
break n | 如果省略n,则表示跳出整个循环,n表示跳出的循环层数 |
continue n | 如果省略n,则表示跳过本次循环,忽略本次循环剩余代码,进入循环的下一次循环,n表示遇到第n层继续循环 |
exit n | 退出当前shell、n为上一次程序指向的状态返回值,n也可以省略,在下一个shell里面可以通过“$?”接收exit n 的n值 |
return n | 用于在函数里作为函数的返回值,判断函数执行是否正确。在下一个代码块里面可以通过“$?”接收return n 的n值 |
命令的基础示例
下面是与break、continue、exit、return相关的示例
[root@oldchang ~]# cat test9-1.sh
#!/bin/bash
if [ $# -ne 1 ]; then #<= 如果传参个数部位1,则打印下面的使用提示
echo $"usage:$0 {break|continue|exit|return}" #<== 分别传入4个命令作为参数
exit 1 #<= 退出脚本
fi
function test(){
for((i=0; i<5; i++));do
if [ $i -eq 3 ];then
$*; #<= 这个地方的"$*" 就是接收函数以外的参数,是{break|continue|exit|return}其中一个
fi
echo $i
done
echo "I am in func." #<= 函数内循环外的输出提示
}
test $* #<= 这里的$*为参数的传参
func_ret=$? #<= 接收并测试函数返回值
if [ `echo $* | grep return |wc -l` -eq 1 ];then #<= 如果传参中含有return
echo "return exit status: $func_ret" #<= 则提示return退出状态
fi
echo "ok"
传入break的结果为
[root@oldchang ~]# sh test9-1.sh break
0
1
2
I am in func.
ok
可以看到,3以后的循环并未执行,这个是因为break及时跳出了循环,但是循环外的echo还在执行
传入continue的结果为
[root@oldchang ~]# sh test9-1.sh continue
0
1
2
4
I am in func.
ok
可以看到,只有3循环没有执行,循环外的echo也在执行,说明到continue的时候,终止了本次循环,继续下一次循环,知道循环正常结束,然后执行后面的语句
传入exit结果为
[root@oldchang ~]# sh test9-1.sh exit
0
1
2
当循环里面的if遇到exit之后,立刻退出了整个程序
传入return的结果为
[root@oldchang ~]# sh test9-1.sh return
0
1
2
return exit status: 0
ok
可以看到,这次没有打印I am in func.这句话,证明在接收到return的时候,整个函数退出了,然后执行非函数的部分
数组
10.1 数组的分类
普通数组:只能使用整数作为索引
关联数组:可以只用字符串作为数组索引
10.2 普通数组
数组名[索引]=变量值
[root@oldchang ~]# linux59[0]=jiaojiao
[root@oldchang ~]# linux59[1]=lili
[root@oldchang ~]# linux59[2]=xuxu
[root@oldchang ~]# echo ${linux59} #<= 使用变量方式查看,其实查看的是数组第一个内容
jiaojiao
[root@oldchang ~]# echo ${linux59[0]} #<= 查看数组第一个元素(0号)
jiaojiao
[root@oldchang ~]# echo ${linux59[1]} #<= 查看数组第二个元素(1号)
lili
[root@oldchang ~]# echo ${linux59[*]} #<= 查看数组的所有元素
jiaojiao lili xuxu
[root@oldchang ~]# echo ${!linux59[*]} #<= 查看数组的所有索引
0 1 2
[root@oldchang ~]# echo ${#linux59[*]} #<= 查看数组元素个数
3
[root@oldchang ~]# linux59[5]=oldchang #<= 使用不连续索引赋值也可以
[root@oldchang ~]# echo ${linux59[*]}
jiaojiao lili xuxu oldchang
[root@oldchang ~]# unset linux59[5] #<= 和变量类似,使用usset即可去掉数组中的的某些值
[root@oldchang ~]# echo ${linux59[*]}
jiaojiao lili xuxu
[root@oldchang ~]# linux59=(a b c d e f g) #<= 数组的批量赋值
[root@oldchang ~]# echo ${linux59[*]}
a b c d e f g
注:通过declare可以看到用户定义的数组
关联数组
定义关联数组
# 首先定义一个关联数组
[root@oldchang ~]# declare -A array_1
# 关联数组赋值
[root@oldchang ~]# array_1[index1]=jiaojiao
[root@oldchang ~]# array_1[index2]=lili
[root@oldchang ~]# array_1[index3]=xixi
# 查看关联数组方式和查看普通数组方式相同,大家可以自己练习一下
数组自增
特殊情况下,可以用关联数组做计数
# 将array[m](关联数组)的值累加
# 先定义关联数组
[root@oldchang ~]# declare -A array_sex
# f解释为female,女性,即关联数组中女性的值自增1
[root@oldchang ~]# let array_sex[f]++
[root@oldchang ~]# let array_sex[f]++
[root@oldchang ~]# let array_sex[f]++
# f解释为male,男性,即关联数组中男性的值自增1
[root@oldchang ~]# let array_sex[m]++
[root@oldchang ~]# let array_sex[m]++
# 查看所有值
[root@oldchang ~]# echo ${array_sex[*]}
3 2
# 查看男性的个数
[root@oldchang ~]# echo ${array_sex[m]}
2
# 查看女性个数
[root@oldchang ~]# echo ${array_sex[f]}
3
练习:
1、 使用两种方法(包括一个数组方式),计算以下数据中性别出现的次数
zhangsan male
lisi female
wangwu male
lili male
xx female
mayun male
mahuateng male
wangjianlin male
cxk unknown
解决方法一
while read line;do
a=`echo $line|awk '{print $2}'`
if [ "$a" = 'male' ];then
let m++
fi
if [ "$a" = "female" ];then
let f++
fi
done <$1
echo "male为$m个"
echo "female为$f个"
执行结果
[root@shell ~/html]# sh sex.sh user.txt
male为6个
female为2个
解决方法2
declare -A array_sex
while read line;do
a=`echo $line|awk '{print $2}'`
if [ "$a" = 'male' ];then
let array_sex[m]++
fi
if [ "$a" = "female" ];then
let array_sex[f]++
fi
done <$1
echo "male为${array_sex[m]}个"
echo "female为${array_sex[f]}个"
执行结果
[root@shell ~/html]# sh sex2.sh user.txt
male为6个
female为2个
案例实操
1、已知下面的字符串是RANDOM随机数变量,经过md5sum之后,再截取一部分连续字符串的结果,请破解这些字符串在使用md5sum处理前对应的数字(使用数组与非数组两种方式)
21029299
00205d1c
a3da1677
1f6d12dd
890684ba
解决:
for ((a=0;a<=32767;a++));do
echo -en "$a\t" >>/tmp/md5.log
echo $a|md5sum|cut -c 1-8 >>/tmp/md5.log
done
while read line;do
grep -w $line /tmp/md5.log
done <$1
RANDOM的取值范围是1-32756.先把1-32756的结果都做一个md5,然后截取前8位数。然后过滤以知道的MD5.
执行结果
[root@shell ~/html]# sh pass.sh md5.txt
25667 21029299
1346 00205d1c
25345 a3da1677
7041 1f6d12dd
10082 890684ba
2、学员信息系统,包括输入学员姓名,年龄,性别,输入指定个数之后,就可以进行查询
echo 0 >/tmp/userid.log
declare -A name
declare -A age
declare -A sex
function luru(){
#for ((i=0;i<=5;i++));do
i=`grep '[0-9]' /tmp/userid.log`
echo '欢迎进入学员信息录入系统'
read -p '请输入你的姓名: ' name
read -p '请输入你的年龄: ' age
read -p '请输入你的性别: ' sex
name[$i]=$name
age[$i]=$age
sex[$i]=$sex
echo '信息录入成功'
echo "$name的身份id为[$i]"
let i++
echo $i >/tmp/userid.log
#done
}
function chaxun(){
echo '欢迎进入学员信息查询系统'
read -p "请输入学员id: " a
echo $a + 0|bc &>/dev/null
if [ "$?" -eq "0" ];then
echo ${name[$a]}
echo ${age[$a]}
echo ${sex[$a]}
else
echo "输入有误"
exit
fi
}
while true;do
cat <<EOF
###########欢迎进入学员信息管理系统#############
1.学员信息录入
2.学员信息查询
3.退出
EOF
read -p "请输入你要选择的功能: " x
case $x in
1)
luru
;;
2)
chaxun
;;
3)
break
;;
*)
echo 输入有误
esac
done
执行结果
[root@shell /server/scripts]# sh xueyuan.sh
###########欢迎进入学员信息管理系统#############
1.学员信息录入
2.学员信息查询
3.退出
请输入你要选择的功能: 1
欢迎进入学员信息录入系统
请输入你的姓名: 葛邦风
请输入你的年龄: 32
请输入你的性别: 男
信息录入成功
葛邦风的身份id为[0]
###########欢迎进入学员信息管理系统#############
1.学员信息录入
2.学员信息查询
3.退出
请输入你要选择的功能: 2
欢迎进入学员信息查询系统
请输入学员id: 0
葛邦风
32
男
trap信号说明
HUP(1) 挂起,通常因终端掉线或用户退出而引发
INT(2) 中断,通常因按下Ctrl+C组合键而引发
QUIT(3) 退出,通常因按下Ctrl+组合键而引发
ABRT(6) 中止,通常因为某些严重的执行错误引发
ALRM(14) 报警,通常用来处理超时
TERM(15) 终止,通常在系统关机时发送
SIGTSTP() 停止进程 终端来的停止信号
trap信号使用
trap “echo ‘想退出,没门’” INT HUP TSTP