流程控制
- 过程式编程语言:
顺序执行
选择执行
循环执行
一.条件选择if语句
类型:选择执行
注意:if语句可嵌套
单分支
if 判断条件;then
条件为真的分支代码
fi
双分支
if 判断条件; then
条件为真的分支代码
else
条件为假的分支代码
fi
多分支
if 判断条件1; then
条件为真的分支代码
elif 判断条件2; then
条件为真的分支代码
elif 判断条件3; then
条件为真的分支代码
else
以上条件都为假的分支代码
fi
逐条件进行判断,第一次遇为“真”条件时,执行其分支, 而后结束整个if语句
注意 type if ——
实验小练习
例题1:判断年龄大小,如果超过20岁,则显示"you are too old"如果小于20岁,则显示"you are so yong"
嵌套方式:
注意:判断数字最好使用[[ "$age" =~ ^[0-9]+$ ]]
例题2:判断文件是否以.sh后缀
else 条件分支例题
例题:判断成绩
二.条件判断:case语句
case 变量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
... *)
默认分支
;;
esac
case支持glob风格的通配符:
*: 任意长度任意字符
?: 任意单个字符
[]:指定范围内的任意单个字符
a|b: a或b
练习1:选择范围内的数字
练习2:编辑菜单并选择
练习3:判断yes or no
三.循环
- 循环执行
将某代码段重复运行多次
重复运行多少次:
循环次数事先已知 循环次数事先未知
有进入条件和退出条件 - for, while, until
(一)for循环
- 格式:
for "变量名——直接写变量名 "in 列表;do
循环体
done
执行机制: 依次将列表中的元素赋值给“变量名”; 每次赋值后即执 行一次循环体; 直到列表中的元素耗尽,循环结束- 列表生成方式:
(1) 直接给出列表
(2) 整数列表: (a) {start..end} (b) $(seq [start [step]] end)
(3) 返回列表的命令 $(COMMAND)
(4) 使用glob,如:.sh
(5) 变量引用; $@, $
例题1:创建十个用户,并设置密码
vim create.sh
#!/bin/bash
2 > /root/user.log
3 for id in {1..10} ; do
4 useradd user$id && echo user$id is created
5 password=`tr -dc 'a-zA-Z0-9'< /dev/urandom |head -c 6`
6 echo user$id:$password >> /root/user.log
7 echo $password |passwd --stdin user$id &> /dev/null
8 passwd -e user$id&> /dev/null——登录后设置新的密码
9 done
删除账号 : for id in {1..10};do userdel -r user$id ;done
或者:echo user{1..10}|xargs -n1 userdel -r
例题2:和172.18.254这个网段的ip进行连接
1 #!/bin/bash
2 netid=172.18.254
3 > /root/ip.log
4 for id in {1..254};do
5 {
6 if ping -c1 -w1 $netid.$id &> /dev/null;then
7 echo $netid.$id |tee -a /root/ip.log
8 fi
9 } &——后台执行,类似并行执行,节省时间
10 done
11 wait——等待时间help wait
wait: wait [id]
Wait for job completion and return exit status.
(二)while 循环
(1)while 的使用格式
while 判断条件 ;do
当判断的条件为真时,执行while 循环
当判断条件为假时,不执行while 循环
执行原理:当使用while 循环时,首先要判断条件的真假,符合条件时,进入循环体执行一次,然后再次判断,直到判断条件为假时,退出循环不在执行
例子1:编写脚本,求100以内所有正奇数之和
#!/bin/bash
i=1
sum=0
while [ $i -lt 100 ];do
let sum+=i
let i=i+2
done
echo "the sum is $sum"
用for 来计算;
#!/bin/bash
sum=0
for i in {1..100..2};do
let sum+=i
done
echo "the sum is $sum"
例题2;编写脚本,提示请输入网络地址,如192.168.0.0,判断 输入的网段中主机在线状态,并统计在线和离线主机各多少
#!/bin/bash
up=0
down=0
hostid=1
read -p "please input the netid:" network
netid=`echo $network| cut -d "." -f1-3`
while [ $hostid -le 10];do
if ping -c1 -w1 $network &> /dev/null;then
echo "the $netid.$hostid is up"
let up++
else
echo "the $netid.$hostid is down"
let down++
fi
let hostid++
done
echo "the up is $up"
echo "the down is $down"
例题三:编写脚本,打印九九乘法表
#!/bin/bash
i=1
while [ $i -le 10 ];do
j=1
while [ $j -le 10 ];do
echo -ne "$j*$i=$[j*i]\t"
let j++
done
let i++
echo
done
例题4;编写脚本,利用变量RANDOM生成10个随机数字,输出 这个10数字,并显示其中的最大值和最小值
max=$ran
min=$ran
i=0
while [ $i -le 10 ];do
ran=$RANDOM
echo $ran
if [ $i -eq 0 ];then
max=$ran
min=$ran
fi
if [ $ran -gt $max ];then
max=$ran
elif [ $ran -lt $min];then
min=$ran
fi
let i++
done
echo "the max is $max"
echo "the min is $min"
例题5:编写脚本,实现打印国际象棋棋盘
#!/bin/bash
i=0
while [ $i -lt 8 ];do
j=0
while [ $j -lt 8 ];do
if [ $[ $[j+i]%2 ] -eq 0 ];do
echo -ne "\033[43m \033[0m\t"
else
echo -ne "\033[41m \033[0m\t"
fi
let j++
done
let i++
echo
done
方法二:
#!/bin/bash
i=0
while [ $i -lt 4 ];do
j=0
while [ $j -lt 8 ];do
if [ $j -lt 4 ];then
echo -ne "\033[41m \033[0m\t"
echo -ne "\033[43m \033[0m\t"
if [ $j -eq 3 ];then
echo
fi
else
echo -ne "\033[43m \033[0m"
echo -ne "\033[41m \033[0m"
fi
if [ $j -eq 7 ];then
echo
fi
let j++
done
let i++
done
while 的特殊用法
- while循环的特殊用法(遍历文件的每一行):
while read line; do 循环体 done < /PATH/FROM/SOMEFILE
依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将 行赋值给变量line
例:查看/etc/passwd中用户的id,如果小于500则为系统用户,大于500位普通用户
while read lines ;do
userid =`echo $lines| cut -d ":" -f3`
username=`echo $lines|cut -d ":" -f1`
if [ $userid-lt 500 ];then
echo "the $username is sysuser"
else echo "the $username is commonuser"
fi
done < /etc/passwd
-
小练习
扫描/etc/passwd文件每一行,如发现GECOS字段为空,则填 充用户名和单位电话为62985600,并提示该用户的GECOS信 息修改成功。
while read lines ;do
GECOS=echo $lines|cut -d ":" -f5
usrename=echo $lines |cut -d ":" -f1
if [ -z $GECOS ];then
chfn -f "$username" -p "62985600" &> /dev/null
echo "the change is successful"
else
echo "the user is not empty"
fi
done < /etc/passwd
- while true; do 循环体 done
示例:检查httpd 的状态,如果处于开启状态,就不执行,如果处于关闭状态,就开启服务,每五秒执行一次,实现实时监控
while true ;do
if killall -0 httpd &> /dev/null ;then
.....
else
systemctl restart httpd &>/dev/null
echo ` date "+%F %T" ` systemctl restart >> /app/httpd.log
fi
sleep5
done
- until false; do 循环体 done
(三)until循环
- 格式: until 判断条件 ;do
循环体
done- 判断条件为假的时候进入循环体,执行命令,与while条件相反
判断条件为为真的时候,退出循环
(四)循环控制语句continue
用于循环体中
continue [N]:
提前结束第N层的本轮循环,而直接进入下一 轮判断;最内层为第1层
while CONDTIITON1; do
CMD1 ...
if CONDITION2; then
continue
fi
CMDn ...
done例1:
i=0
while [ $I -le 9 ];do
if [ $i -qe 5 ];then
continue
fi
echo i=$i
let i++
done
如果只是不显示5,而后续的数字继续打印,则
i=0
while [ $i -le 10 ];do
let i++
if [ $i -eq 5 ];then
continue
else
echo i=$i
fi
done
例2
for i in {1..10};do
for j in {1..10};do
echo -n "$j "
if [ %j -eq 5 ];then
continue 2
fi
done
echo
done
此时为continue 2,所以结束了第二层的本轮循环,也就是最外层循环
(五)循环控制语句break
用于循环体中
break [N]:提前结束第N层循环,最内层为第1层 ——简单来说就是退出第N层整体的循环
while CONDTIITON1; do
CMD1 ...
if CONDITION2; then
break
fi
CMDn ...
done
例题;打印行和列
for i in {1..10};do
for j in {1..10};do
echo -n "$j "
[ $j -eq 5 ]&&break
done
echo
done
当输入break 2 时,整个外层循环都结束只打印 "1 2 3 4 5"
(六)循环控制shift命令
shift [n]
用于将参量列表 list 左移指定次数,缺省为左移一次。
参量列表 list 一旦被移动,最左端的那个参数就从列表中删 除。
while 循环遍历位置参量列表时,常用到 shift
示例:
whlie [ $# -gt 0 ];do
echo "$*"
shilt
done
因此该命令可以用来创建用户
while [ $# -gt 0 ];do
id $i /dev/null && continue
useradd $i && echo $i is created
shift
done
(七)特殊用法 for循环的特殊格式
- 双小括号方法,即((…))格式,也可以用于算术运算
*双小括号方法也可以使bash Shell实现C语言风格的变量操作
I=10
((I++))
for循环的特殊格式:
for ((控制变量初始化;条件判断表达式;控制变量的修正表达 式))
do
循环体
done
控制变量初始化:仅在运行到循环代码段时执行一次
控制变量的修正表达式:每轮循环结束会先进行控制变量修 正运算,而后再做条件判断
例:用for的特殊循环格式实现1-100的加法运算
sum=0
for (( i=0;i<=100;i++ ));do
let sum+=i
done
echo "the sum is $sum"
unset sum
(八)select循环与菜单
select variable in list
do
循环体命令
done
select 循环主要用于创建菜单,按数字顺序排列的 菜单项将显示在标准错误上,并显示 PS3 提示符, 等待用户输入
用户输入菜单列表中的某个数字,执行相应的命令
用户输入被保存在内置变量 REPLY 中
select 是个无限循环,因此要记住用 break 命令退 出循环,或用 exit 命令终止脚本。也可以按 ctrl+c 退出循环
select 经常和 case 联合使用
与 for 循环类似,可以省略 in list,此时使用位置 参量
例子:选择菜单
#!/bin/bash
PS3=" please input your menu: "
select menu in lamian chaomian chaofan jiaozi baozi ;do
case $REPLY in
1)
echo "the price is 10"
;;
2)
echo "the price is 15"
;;
3)
echo " the price is 10 "
;;
4)
echo "the price is 20"
;;
5)
echo "the price is 10"
;;
*)
echo "get out!"
break # select 本身是死循环,如果不执行break命令,则不会退出循环
;;
esac
done
(九)信号捕捉trap
- trap '触发指令' 信号 自定义进程收到系统发出的指定信号后,将执行触发指令 ,而不会执行原操作
- trap '' 信号 忽略信号的操作
- trap '-' 信号 恢复原信号的操作
trap -p 列出自定义信号操作
例:
#!/bin/bash
trap 'echo "please press crtl+c" ' int #此命令是int功能失效,只是打印"please press crtl+c"
trap -p
for ((i=1;i<=20;i++));do
echo $i
sleep1
done
trap ' ' int # 忽略该操作
trap -p
for ((i=1;i<=20;i++));do
echo $i
sleep1
done
trap '_' int # 恢复int命令的操作
trap -p
for ((i=1;i<=20;i++));do
echo $i
sleep1
done