目录
一、for 循环语句
1、for 语句的结构
2、for 语句应用示例
(1)根据姓名列表批量添加用户
(2)根据IP地址列表检查主机状态
二、使用 while 循环语句
1、while 语句的结论
2、while 语句应用示例
(1)批量添加规律编号的用户
(2)猜价格游戏
三、until 循环语句
1、until 语句的结构
2、until 语句应用示例
(1)计算1-50的和
循环语句在Shell编程十分重要,是自动化处理重复任务的利器。
使用 for 循环语句时,需要指定一个变量及可能的取值列表,针对每个不同的取值重复执行相同的命令序列,直到变量值用完退出循环。
“取值列表”称为for语句的执行条件,其中包括多个属性相同的对象,需要预先指定(如通讯录、IP黑名单)。
语句结构如下:
for 变量名 in 取值列表
do
命令序列
done
for语句的操作对象为用户指定名称的变量,并通过 in 关键字为该变量预先设置了一个取值列表,多个取值之间以空格进行分隔。位于 do...done 之间的命令序列称为循环体,其中的执行语句需要引用变量以完成相应的任务。
for 语句的执行流程:首先将列表中的第一个取值赋给变量,并执行 do...done 循环体中的命令序列;然后将列表中的第二个取值赋给变量,并执行循环体中的命令序列.…依此类推,直到列表中的所有取值用完,最后将跳至 done 语句,表示结束循环。
编辑需要用到的文件
vim /root/users.txt #用做测试的列表文件
aaa
bbb
ccc
zhangsan
lisi
wangwu
vim uaddfor.sh #批量添加用户的脚本
#!/bin/bash
ULIST=$(cat /root/users.txt)
for UNAME in $ULIST
do
useradd $UNAME
echo "123456" | passwd --stdin $UNAME &>/dev/null
done
chmod +x uaddfor.sh #给执行权限
./uaddfor.sh #运行脚本
tail -8 /etc/passwd #测试并确认执行结果
unbound:x:996:993:Unbound DNS resolver:/etc/unbound:/sbin/nologin
chrony:x:995:992::/var/lib/chrony:/sbin/nologin
aaa:x:1000:1000::/home/aaa:/bin/bash
bbb:x:1001:1001::/home/bbb:/bin/bash
ccc:x:1002:1002::/home/ccc:/bin/bash
zhangsan:x:1003:1003::/home/zhangsan:/bin/bash
lisi:x:1004:1004::/home/lisi:/bin/bash
wangwu:x:1005:1005::/home/wangwu:/bin/bash
若要删除uaddfor.sh脚本所添加的用户,只需参考上面脚本代码,将for循环体中添加用户的命令序列改为删除用户的操作即可。
vim udelfor.sh #批量删除用户的脚本
#!/bin/bash
ULIST=$(cat /root/users.txt)
for UNAME in $ULIST
do
userdel -r $UNAME &>/dev/null
done
chmod +x udelfor.sh
tail -3 /etc/passwd #会发现之前创建的用户都已经没了
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
unbound:x:996:993:Unbound DNS resolver:/etc/unbound:/sbin/nologin
chrony:x:995:992::/var/lib/chrony:/sbin/nologin
vim /root/ipadds.txt #用作测试的列表文件
192.168.10.101
192.168.10.110
127.0.0.1
192.168.20.101
vim chkhosts.sh #循环检查各主机的脚本
#!/bin/bash
HLIST=$(cat /root/ipadds.txt)
for IP in $HLIST
do
ping -c 3 -i 0.2 -W 3 $IP &>/dev/null
if [ $? -eq 0 ]
then
echo "Host $IP is UP"
else
echo "Host $IP is down"
fi
done
chmod +x chkhosts.sh #给权限
./chkhosts.sh #测试并确认执行结果
Host 192.168.10.101 is UP
Host 192.168.10.110 is down
Host 127.0.0.1 is UP
Host 192.168.20.101 is down
上述脚本代码中,do…done循环体内嵌套使用了 if 条件选择语句,用来针对不同 IP 地址的测试结果进行判断,并输出相应的提示信息。嵌套可以理解为镶嵌、套用,就是在已有的语句、函数中在多加一个或多个语句、函数等。实际上,if 语句、for 语句及其他各种 Shell 脚本语句都是可以嵌套使用的。
for 循环语句非常适用于列表对象无规律,且列表来源已固定(如某个列表文件)的场合。而对于要求控制循环次数、操作对象按数字顺序编号、按特定条件执行重复操作等情况,则更适合使用另外一种循环——while 语句。
使用 while 循环语句时,可以根据特定的条件反复执行一个命令序列,直到该条件不再满足时为止。在脚本应用中,应该避免出现死循环的情况,否则后边的命令操作将无法执行。因此,循环体内的命令序列中应包括修改测试条件的语句,以便在适当的时候使测试条件不再成立,从而结束循环。
语法结构如下:
while 条件测试操作
do
命令序列
done
while 语句的执行流程:首先判断 while 后的条件测试操作结果,如果条件成立,则执行 do...done循环体中的命令序列;返回 while后再次判断条件测试结果,如果条件仍然成立,则继续执行循环体;再次返回到 while 后,判断条件测试结果…...如此循环,直到 while 后的条件测试结果不再成立为止,最后跳转到 done 语句,表示结束循环。
使用 while 循环语句时,有两个特殊的条件测试操作,即 true(真)和 false(假)。使用 true作为条件时,表示条件永远成立,循环体内的命令序列将无限执行下去,除非强制终止脚本(或通过 exit语句退出脚本);反之,若使用 false 作为条件,则循环体将不会被执行。这两个特殊条件也可以用在 if 语句的条件测试中。
vim uaddwhile.sh #添加用户的脚本
#!/bin/bash
PREFIX="stu"
i=1
while [ $i -le 10 ]
do
useradd ${PREFIX}$i
echo "123456" | passwd --stdin ${PREFIX}$i &>/dev/null
let i++
done
上述脚本代码中,使用变量 i 来控制用户名称的编号,初始赋值为 1,并且当取值大于 10 时终止循环。在循环体内部,通过语句“let i++”(等同于 i='expr $i +1`)来使变量 i 的值增加 1,因此当执行第一次循环后 i 的值将变为 2,执行第二次循环后 i的值将变为 3,…,依此类推。
chmod +x uaddwhile.sh
./uaddwhile.sh
grep "stu" /etc/passwd | tail -3
stu8:x:1007:1007::/home/stu8:/bin/bash
stu9:x:1008:1008::/home/stu9:/bin/bash
stu10:x:1009:1009::/home/stu10:/bin/bash
若要删除 uaddwhile.sh 脚本所添加的用户,只需参考上述脚本代码,将 while 循环体中添加用户
的命令序列改为删除用户的操作即可。
vim udelwhile.sh
#!/bin/bash
PREFIX="stu"
i=1
while [ $i -le 10 ]
do
userdel -r ${PREFIX}$i
let i++
done
chmod +x udelwhile.sh
./udelwhile.sh #测试并确认执行结果
cat /etc/passwd #会发现已经删除了之前创建的用户
vim pricegame.sh
#!/bin/bash
PRICE=$(expr $RANDOM % 1000)
TIMES=0
echo "商品实际价格范围为0-999,猜价格是多少?"
while true
do
read -p "请输入你猜测的价格数目:" INI
let TIMES++
if [ $INI -eq $PRICE ]
then
echo "恭喜你答对了,实际价格是$PRICE"
echo "你总共猜测了$TIMES次"
exit 0
elif [ $INI -gt $PRICE ]
then
echo "太高了!"
else
echo "太低了!"
fi
done
chmod +x pricegame.sh
./pricegame.sh
商品实际价格范围为0-999,猜价格是多少?
请输入你猜测的价格数目:777
太高了!
请输入你猜测的价格数目:444
太高了!
请输入你猜测的价格数目:333
太高了!
请输入你猜测的价格数目:111
太高了!
请输入你猜测的价格数目:77
太高了!
请输入你猜测的价格数目:55
太低了!
请输入你猜测的价格数目:66
太高了!
请输入你猜测的价格数目:50
太低了!
请输入你猜测的价格数目:54
太低了!
请输入你猜测的价格数目:55
太低了!
请输入你猜测的价格数目:56
太低了!
请输入你猜测的价格数目:58
恭喜你答对了,实际价格是58
你总共猜测了12次
until 循环与 while 循环类似,while 循环能实现的脚本 until 同样也可以实现,但区别是while循环在条件为真是继续执行循环,而until 则是在条件为假时执行循环。
语法结构如下:
until 条件测试操作
do
命令序列
done
until 语句的执行流程:首先判断 until 后的条件测试操作结果,如果条件不成立,则执行 do...done循环体中的命令序列;返回 until 后再次判断条件测试结果,如果条件仍然不成立,则继续执行循环体;再次返回到 until 后,判断条件测试结果…...如此循环,直到 until 后的条件测试结果成立为止,最后跳转到 done 语句,表示结束循环。
vim sum1to50.sh
#!/bin/bash
i=0;s=0
until [ $i -eq 50 ]
do
let "i=$i+1";let "s=$s+$i"
done
echo 'sum(1..50)=' $s
chmod +x sum1to50.sh
./sum1to50.sh
sum(1..50)= 1275
上述代码中,在 i 的值小于 50 之前,每次循环 i 的值加 1,并且求出 s 的值。