Shell可以重复地执行特定的指令,直到特定的条件被满足为止。这重复执行的一组指令就叫做循环
特点:
- 首先,循环条件中使用的变量必须是已初始化的,然后在循环中开始执行
- 每次在循环开始时进行一次测试
- 重复地执行一个代码块
循环实例
(一)for循环语法
javascript
for 循环地基本语法:
for VAR in iteml item1 item2 ... itemN
do
command1
command2
...
commandN
done
for循环变量的内容的语法
javascript
for VAR in $fileNames
do
command1
command2
...
commandN
done
for循环命令替换的语法
javascript
for VAR in $(Linux-command-name)
do
command1
command2
...
commandN
done
for循环还有三项表达式语法,这种语法与c语言中常见的for循环使用的方法相同,其语法如下:
javascript
for VAR in (( EXP1;EXP2;EXP3))
do
command1
command2
...
commandN
done
上述语法以三项参数循环控制表达式为特征,它由一个初始化式(EXP1),循环测试或条件(EXP2)和一个计算表达式(EXP3)组成。
(二)for循环实例
在 for循环中,每次指定列表中的(iterml...itermN)新值被赋给变量VAR 后,for循环都会执行一次,它将重复运行do和 done 之间的所有语句,直到条件不满足时为止。
这些列表或数值通常是:
- 字符串;
数字;
命令行参数;
文件名;
Linux 命令的输出。
我们来看一个简单的使用for循环的脚本:
脚本应用示例
- 任务目标
- 批量添加用户账号(名称无规律)
javascript
[root@controller ~]# cat uaddfor.sh
#!/bin/bash
#######################################################
#
# FILE:uaddfor.sh
# USAGE: ./uaddfor.sh
#
# DESCRTPTION:
# OPTIONS: --
# REPUIREMENTS: --
# BUGS: --
# NOTES: --
# AUTHOR: LEY
# ORGANIZATION:
# CREATED: 04/17/2024 15:50
# REVISION: --
#####################################################
ULIST=$(cat /root/users.txt)
for UNAME in $ULIST
do
useradd $UNAME
echo "123456" | passwd --stdin $UNAME
done
[root@controller ~]# cat users.txt
zhangsan
lisi
wangwu
[root@controller ~]# ./uaddfor.sh
Changing password for user zhangsan.
passwd: all authentication tokens updated successfully.
Changing password for user lisi.
passwd: all authentication tokens updated successfully.
Changing password for user wangwu.
passwd: all authentication tokens updated successfully.
[root@controller ~]# tail -3 /etc/passwd
zhangsan:x:1001:1001::/home/zhangsan:/bin/bash
lisi:x:1002:1002::/home/lisi:/bin/bash
wangwu:x:1003:1003::/home/wangwu:/bin/bash
这个脚本不够完善,我们将其完善一下,判断用户是否存在,是否需要重新创建用户。
javascript
#!/bin/bash
#######################################################
#
# FILE:uaddfor.sh
# USAGE: ./uaddfor.sh
#
# DESCRTPTION:
# OPTIONS: --
# REPUIREMENTS: --
# BUGS: --
# NOTES: --
# AUTHOR: LEY
# ORGANIZATION:
# CREATED: 04/17/2024 15:50
# REVISION: --
#####################################################
ULIST=$(cat /root/users.txt)
for UNAME in $ULIST
do
id $UNAME &>/dev/null
if [ $? -eq 0 ]
then
echo "用户 $UNAME 已存在。"
read -p "是否要重新创建 (y/yes|n/no): " ans
if [ "$ans" == 'yes' ] || [ "$ans" == 'y' ]
then
userdel -r $UNAME
echo "用户 $UNAME 已删除。"
useradd $UNAME
echo "123456" | passwd --stdin $UNAME
echo "用户 $UNAME 创建成功。"
else
echo "用户 $UNAME 未被删除。"
fi
else
useradd $UNAME
echo "123456" | passwd --stdin $UNAME
echo "用户 $UNAME 创建成功。"
fi
done
再追加日志,将删除用户的信息和日期写入日志
javascript
[root@controller ~]# vim uaddfor.sh
#!/bin/bash
#######################################################
#
# FILE:uaddfor.sh
# USAGE: ./uaddfor.sh
#
# DESCRTPTION:
# OPTIONS: --
# REPUIREMENTS: --
# BUGS: --
# NOTES: --
# AUTHOR: LEY
# ORGANIZATION:
# CREATED: 04/17/2024 15:50
# REVISION: --
#####################################################
ULIST=$(cat /root/users.txt)
#测试代码,删除/root/users.txt文件中,所有用户
# for UNAME in $ULIST
#do
# userdel -r $UNAME
#done
#主功能,按照/root/users.txt文件中用户名,新建用户并设置密码为123456
for UNAME in $ULIST
do
#判断UNAME是否存在id加用户名如果存在则输出用户信息,不存在则输出不存在,将所有结果丢进/dev/null文件
id $UNAME &>/dev/null
if [ $? -eq 0 ]
then
#存在则用户输入是否需要重新创建
echo "用户 $UNAME 已存在。"
read -p "是否要重新创建 (y/yes|n/no): " ans
if [ "$ans" == 'yes' ] || [ "$ans" == 'y' ]
then
#输入yes则删除用户重新创建
userdel -r $UNAME
#将删除用户的信息和日期写入日志
echo "用户 $UNAME 已删除。" >>/etc/rsyslog.conf
date &>>/etc/rsyslog.conf
useradd $UNAME
echo "123456" | passwd --stdin $UNAME
echo "用户 $UNAME 创建成功。"
else
echo "用户 $UNAME 未被删除。"
fi
else
useradd $UNAME
echo "123456" | passwd --stdin $UNAME
echo "用户 $UNAME 创建成功。"
fi
done
C语言风格的for循环
- 通过控制变量,条件成立时循环
- 步长可控次数
javascript
[root@controller ~]# cat cfor.sh
#!/bin/bash
for ((i=1;i<=5;i+=2))
do
echo $i
done
[root@controller ~]# chmod +x cfor.sh
[root@controller ~]# ./cfor.sh
1
3
5
- 使用 for 循环遍历局域网中的 IP 地址,从 10.0.0.1 到 10.0.0.254。
- 对每个 IP 地址执行一次 ping 命令,发送一个 ICMP 请求并等待回应,超时时间为1秒。
- 如果主机对 ICMP 请求有响应(即返回状态码为0),则输出 "Host $host is up.",表示主机是可达的。
- 如果主机没有响应,则输出 "Host $host is down.",表示主机不可达。
javascript
#!/bin/bash
for ((i=1;i<=254;i+=1)) do
host="10.0.0.$i"
ping -c 1 -i 0.2 -W 1 $host &> /dev/null
if [ $? -eq 0 ]; then
echo "Host $host is up."
else
echo "Host $host is down."
fi
done
(三)while循环语法
while循环语句用于重复地执行一个命令列表
while循环语句的语法如下所示:
javascript
while [ CONDITION ]
do
command1
command2
...
commandN
done
当条件CONDITION为真时,循环体将被逐行执行
(四)while循环实例------菜单驱动程序
javascript
$ cat whilemenu.sh
#!/bin/bash
#######################################################
#
# FILE:whilemenu.sh
# USAGE: ./whilemenu.sh
#
# DESCRTPTION:
# OPTIONS: --
# REPUIREMENTS: --
# BUGS: --
# NOTES: --
# AUTHOR: LEY
# ORGANIZATION:
# CREATED: 04/25/2024 16:04
# REVISION: --
#####################################################
while :
do
clear #清理终端
echo "======================================="
echo " MAIN - MENU "
echo "======================================="
echo "1. Dispaly date and time."
echo "2. Dispaly system information."
echo "3. Dispaly what users are doing."
echo "4. exit."
read -p "Enter your choice [ 1-4 ]: " choice #从标准输入中读取用户的输入,并赋值给变量choice
case $choice in
1)
echo "Today is $(date +%Y-%m-%d)." #打印当前日期,格式为YYYY-MM-DD
echo "Current time : $(date +%H:%M:%S)." #打印当前时间格式为hh:mm:ss
read -p "Press [Enter] key to continue..." readEnterKey#只读入换行符
;;
2)
uname -a #打印系统信息
read -p "Press [Enter] key to continue..." readEnterKey
;;
3)
w #显示系统当前登录的用户,及用户当前运行命令
read -p "Press [Enter] key to continue..." readEnterKey
;;
4)
echo "Bye!!!"
exit 0
;;
*)
echo "Error: Inalid option!"
read -p "Press [Enter] key to continue..." readEnterKey
;;
esac
done
此脚本的运行结果如下图:
(五)until循环语句实例
until循环与while循环类似,也同样基于一个类似的条件。但until循环的判断条件正好与while循环的判断条件相反,until循环在条件为假的时候运行。一旦条件满足,即为真,就会退出循环。until循环的语法如下所示:
javascript
until [ CONDITION ]
do
command1
command2
...
commandN
done
until循环与while循环相比:
- until循环执行直到状态返回0
- while循环执行直到返回非0状态
- until循环总是执行至少一次
javascript
$ cat untilloop.sh
#!/bin/bash
#######################################################
#
# FILE:untilloop.sh
# USAGE: ./untilloop.sh
#
# DESCRTPTION:
# OPTIONS: --
# REPUIREMENTS: --
# BUGS: --
# NOTES: --
# AUTHOR: LEY
# ORGANIZATION:
# CREATED: 04/24/2024 16:30
# REVISION: --
#####################################################
var=1
until [ $var -gt 3 ]
do
echo "The for loop is run $var times."
var=$(( var + 1 ))
done
$ chmod +x untilloop.sh
$ ./untilloop.sh
The for loop is run 1 times.
The for loop is run 2 times.
The for loop is run 3 times.