第五章流程控制之循环
5.1 for循环
-
for循环是最简单,也是最常用的循环语句。与其他的程序设计语言一样,for循环都是初学者在学习循环结构时的入门课程。for循环通常用于遍历整个对象或者数字列表。按照循环条件的不同,for循环语句可以分为带列表的for循环、不带列表的for循环以及c风格的for循环。
5.1.1 带列表的for循环
- 格式:
for variable in {list}
do
statement1
statement2
...
done
- 分析
1.variable称为循环变量
2.list是一个列表,可以时一系列的数字或者字符串,元素之间使用空格隔开
3.do和done 之间的所有的语句称为循环体,即循环结构中重复执行的语句
4.执行时,shell会将in关键字后面的list列表的第一个元素的值赋给变量variable,然后执行循环体,当循环体中的语句执行完毕之后剩余以此类推,当list列表中的所有的元素都被访问后,for循环结构终止,程序将继续执行done语句后面的其他的语句。
- 例1:
[root@server ~]# vim for1.sh
#!/bin/bash
for IP in 192.168.145.125 192.168.145.127
do
echo $IP
done
~
[root@server ~]# bash for1.sh
192.168.145.125
192.168.145.127
[root@server ~]# vim for2.sh
#!/bin/bash
for IP in 192.168.145.{125..130}
do
echo $IP
done
[root@server ~]# bash for2.sh
192.168.145.125
192.168.145.126
192.168.145.127
192.168.145.128
192.168.145.129
192.168.145.130
- 例2:获取目录下所有目录的文件名
[root@server ~]# vim for3.sh
#!/bin/bash
for FILE in $(ls -F / | grep /$)
do
echo $FILE
done
#ls -F 表示按照文件类型进行归类显示,会在不用的文件名尾部增加不同类型符号已进行区分,目录以/结尾、链接文件以@结尾、执行文件以*结尾等
#grep /$ 表示过滤以/结尾内容
[root@server ~]# bash for3.sh
afs/
boot/
day04/
dev/
etc/
file/
helen/
home/
media/
mnt/
- shell允许用户指定for语句步长,格式如下
- 例3: 计算1+2+3+....+100,的结果
[root@server ~]# vim for4.sh
#!/bin/bash
sum=0
for i in {1..100..1}
do
let sum=sum+i
done
echo "sum=$sum"
[root@server ~]# bash for4.sh
sum=5050
5.1.2 不带列表的for循环
- 原则:for 不提供循环列表,shell将从命令行获取循环列表数据及条件,格式:
for variable in {list}
do
statement1
statement2
...
done
- 由于系统变量$@可以获取所有位置参数,以上的语法等价于:
for variable in $@或$*
do
statement1
statement2
...
done
- 例4:
[root@server ~]# vim for5.sh
#!/bin/bash
for arg
do
echo $arg
done
[root@server ~]# bash for5.sh {1..10}
1
2
3
4
5
6
7
8
9
10
5.1.3 基于c语言风格的for循环
- 格式
for ((初始化:条件表达式:步长)) #注意:2个圆括号
do
statement1
statement2
...
done
- 例面试题,批量创建用户
[root@server ~]# vim for6.sh
#!/bin/bash
for ((i=1;i<=10;i++))
do
if ! id -u test$i &> /dev/null
then
useradd test$i
echo "123456" | passwd --stdin test$i &> /dev/null
else
echo "test$i is exists"
fi
done
[root@server ~]# bash for6.sh
- 注意: i++表示滞后自增,++i表示滞前自增
5.2 while 循环
5.2.1 格式
while expression
do
statement1
statement2
...
done
-
上例语法中,expression表示条件表达式,循环必须满足该表达式 ,循环必须满足该表达式,否则循环结束,可以是任何符合语法的shell命令,但推荐是写测试表达式
5.2.2 while循环读取文件
[root@server ~]# vim while1.sh
#!/bin/bash
exec < file.txt
while read a
do
echo $a
done
#exec < file.txt 将file.txt 文件内容读入到标准输入中
#read a 表示从标准输入中按照行读取内容到变量a
[root@server ~]# bash while1.sh
data12
data11
data10
data9
data8
data7
data6
data5
data4
data3
data2
#法2:使用cat读取文件,通过管道符进入while循环处理
cat 文件名 | while read line
do
statement1
statement2
...
done
#法3: 通过while循环尾部使用输入重定向指定输入数据
while read line
do
statement1
statement2
...
done < 文件名
5.2.3 while语句示例
-
例6: 猜商品价格 ,通过
[root@server ~]# vim while2.sh
#!/bin/bash
PRICE=$[ $RANDOM%20 ]
count=0
while true
do
read -p "请输入【0-20】之间的价格:" INT
let count++
if [ $INT -eq $PRICE ] #等于比较
then
echo "恭喜你,猜对了"
echo "你猜了$count次机会"
exit 0 #退出程序
elif [ $INT -gt $PRICE ] #大于比较
then
echo "你输入的商品价格高了"
else
echo " 你输入的商品价格低了"
fi
done
[root@server ~]# bash while2.sh
请输入【0-20】之间的价格:5
你输入的商品价格低了
请输入【0-20】之间的价格:10
你输入的商品价格低了
请输入【0-20】之间的价格:15
你输入的商品价格高了
请输入【0-20】之间的价格:13
恭喜你,猜对了
你猜了4次机会
- 例7:将例5中批量创建的账户删除
[root@server ~]# vim while3.sh
#!/bin/bash
i=1
while [ $i -le 5 ]
do
if id -u test$i &> /dev/null
then
userdel -r test$i
else
echo "test$i 不存在"
fi
let i++
done
[root@server ~]# bash while3.sh
[root@server ~]# bash while3.sh
test1 不存在
test2 不存在
test3 不存在
test4 不存在
test5 不存在
5.3 until循环
5.3.1 作用
- until 循环不断地重复执行循环中的语句,直至某个条件不成立
until expression
do
statement1
statement2
...
done
- expression 是一个条件表达式,值不为0时,执行do与done之间的语句,值为0时退出until循环
5.3.2示例
- 删除账户改写
[root@server ~]# vim un1.sh
#!/bin/bash
i=6
until [ $i -gt 10 ]
do
if id -u test$i &> /dev/null
then
userdel -r test$i
else
echo "test$i不存在"
fi
let i++
done
[root@server ~]# bash un1.sh
[root@server ~]# bash un1.sh
test6不存在
test7不存在
test8不存在
test9不存在
test10不存在
5.4 循环控制
5.4.1 组成
- break :是立即跳出某个循环结构。break语句可以用在for、while或者until等循环语句的循环体中
- continue 作用不是退出循环体。而是跳过当前循环体中该语句后面的语句,重新从循环语句开始的位置执行
5.4.2 详细语法:
命令 | 说明 |
break n | 如果省略n,则表示跳出整个循环,n表示跳出循环的层数 |
continue n | 如果省略n,则表示跳过本次循环,忽略本次循环的剩余代码,进入循环的下一次循环。 |
exit n | 退出当前shell程序,n为上一次程序执行的状态返回值。n也可以省略,在下一个shell里可通过”$?“ 接受exit的n值 |
return n | 用于在函数里作为函数的返回值,以判断函数执行是否正确。在下一个shell里可通过”$?“ 接受exit的n值 |
5.4.3示例
- 例9:判断素数
[root@server ~]# vim for7.sh
#!/bin/bash
read -p "请输入一个正整数:" prime
if ((prime<2))
then
echo "数据错误,请输入大于等于2的正整数!"
else
for ((i=2;i<prime;i++))
do
if ((prime%i==0))
then
echo "平数"
break
fi
done
if ((i==prime))
then
echo "素数"
fi
fi
[root@server ~]# bash for7.sh
请输入一个正整数:5
素数
[root@server ~]# bash for7.sh
请输入一个正整数:20
平数
- 例10 :计算100到150之间不能被3整除的数,输出是一行显示5行
[root@server ~]# vim for8.sh
#!/bin/bash
count=0
for ((i=100;i<=150;i++))
do
if ((i%3==0))
then
continue #若i能被3整除,则continue执行,执行下一次循环
fi
echo -ne "$i\t" #——ne 取消echo输出的最后换行符,并启用转义字符功能
let count++ #计数器
if ((count%5==0))
then
echo
fi
done
echo
[root@server ~]# bash for8.sh
100 101 103 104 106
107 109 110 112 113
115 116 118 119 121
122 124 125 127 128
130 131 133 134 136
137 139 140 142 143
145 146 148 149 150
5.4.4 循环嵌套
- 例11:打印99乘法表
[root@server ~]# vim for9.sh
#!/bin/bash
for i in `seq 9` #seq 9 产生1-9的列表,使用反引号声明为命令
do
for j in `seq 9`
do
[ $j -le $i ] && echo -ne "$i*$j=`echo $(($i*$j))`\t"
done
echo #输出换行
done
[root@server ~]# bash for9.sh
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
- 例12:打印三角形
[root@server ~]# vim for10.sh
#!/bin/bash
for ((i=1;i<10;i++))
do
for ((j=1;j<=10-i;j++))
do
echo -n " "
done
for ((k=1;k<=i;k++))
do
echo -n "$i "
done
echo
done
[root@server ~]# bash for10.sh
1
2 2
3 3 3
4 4 4 4
5 5 5 5 5
6 6 6 6 6 6
7 7 7 7 7 7 7
8 8 8 8 8 8 8 8
9 9 9 9 9 9 9 9 9