五、流程控制之循环

五、流程控制之循环

5.1 for循环

  1. 带列表的for循环

    执行时Shell会将in关键字后面列表的第1个元素的值赋给变量var,然后执行循环体,当循环体中的语句执行完毕之后,将第2个元素的值赋给变量以此类推,当列表中的所有的元素都被访问后,for循环结构终止,程序将继续执行done语句后面的其他语句。

    bash 复制代码
    #格式1:{}中可以是一系列的数字或者字符串;例如:{1,2,3},{1..10},{1..10..2}表示10以内的奇数,{a..z},{a..z..2}等
    for var in {1..10}
    do 
         command
    done
    #格式2:命令执行后的输出作为for循环列表中的循环值
    for var in `command`
    do
    	command
    done

    示例1:

    bash 复制代码
    [root@server ~]# mkdir /shell/chap05
    [root@server ~]# vim /shell/chap05/for1.sh
    #!/bin/bash
    echo for1:
    for ip in 192.168.168.10 192.168.168.20
    do
            echo $ip
    done
    
    echo for2:
    for ip in 192.168.168.{10..20..2}
    do
            echo $ip
    done
    [root@server ~]# bash /shell/chap05/for1.sh
    for1:
    192.168.168.10
    192.168.168.20
    for2:
    192.168.168.10
    192.168.168.12
    192.168.168.14
    192.168.168.16
    192.168.168.18
    192.168.168.20

    示例2:

    bash 复制代码
    [root@server ~]# vim /shell/chap05/for2.sh
    #!/bin/bash
    sum=0
    for i in {1..100..2}
    do
            sum=$[$sum+$i]
    done
    echo sum=$sum
    
    sum1=0
    for j in $(seq 1 2 100)
    do
            sum1=$[$sum1+$j]
    done
    echo sum1=$sum1
    [root@server ~]# bash /shell/chap05/for2.sh
    sum=2500
    sum1=2500

    示例3:

    bash 复制代码
    [root@server ~]# vim /shell/chap05/for3.sh
    #!/bin/bash
    for file in $(ls -F / | grep /$)
    do
            echo $file
    done
    [root@server ~]# bash /shell/chap05/for3.sh
    afs/
    boot/
    dev/
    etc/
    home/
    media/
    mnt/
    opt/
    proc/
    root/
    run/
    shell/
    srv/
    sys/
    tmp/
    usr/
    var/
    # ls -F  :用于将目录内的文件按照文件类型进行归类显示,会在不同类别的文件名尾部增加不同的标识符,目录以/结尾、链接文件以@结尾、可执行文件以*结尾、普通文件无符号
    # grep /$ :表示以/结尾的行
  2. 不带列表的for循环:for不提供循环列表,shell将从命令行获取循环列表数据。

    bash 复制代码
    #格式1:此种写法等同于格式2的写法
    for var 
    do
    	command
    done
    #格式2:
    for var in $@或$*
    do
    	command
    done
    bash 复制代码
    [root@server ~]# vim /shell/chap05/for4.sh
    #!/bin/bash
    echo for1:
    for num
    do
            echo $num
    done
    
    echo for2:
    for num in $*
    do
            echo $num
    done
    [root@server ~]# bash  /shell/chap05/for4.sh 1 2 3 4 5
    for1:
    1
    2
    3
    4
    5
    for2:
    1
    2
    3
    4
    5
  3. 基于C语言风格的for循环

bash 复制代码
for ((expression1;expression2;expression3))
#for ((i=1;i<=30;i++))
do
	command
done
bash 复制代码
[root@server ~]# vim /shell/chap05/for5.sh
#!/bin/bash
for ((i=1;i<=10;i++))
do
        if  id  test$i &> /dev/null
        then
                echo "test$i 已存在!"
        else
                useradd test$i
                echo "123456" | passwd --stdin test$i &> /dev/null
        fi
done
[root@server ~]# bash /shell/chap05/for5.sh

5.2 while循环

当条件成立则继续执行循环体里面的语句

bash 复制代码
#用法1:表达式为真则继续循环,为假停止循环
    while expression
    do
      command
    done
#用法2:命令执行后返回状态码为0则为真,继续循环
    while 命令
    do
      command
    done
#用法3:死循环
    while true
    do
      command
    done
#用法4:死循环
    while :
    do
      command
    done

使用while循环读取文件内容:

bash 复制代码
#写法1:exec < file将file文件中的内容读到标准输入中,read a表示从标准输入读取内容给变量a
    #!/bin/bash
    exec < file
    while read a
    do
      echo $a
    done
#写法2:使用cat读取文件,通过管道符进入while循环处理
    #!/bin/bash
    cat file | while read a
    do
      echo $a
    done
#写法3:在while循环尾部使用输入重定向指定输入数据
    #!/bin/bash
    while read a
    do
      echo $a
    done < file

示例1:

bash 复制代码
[root@server ~]# vim /shell/chap05/while1.sh
#!/bin/bash
i=1
while [ "$i" -le 10 ]
do
        if id test$i &> /dev/null
        then
                userdel -r test$i
        else
                echo "test$i 账户已删除"
        fi
        let i++
done
[root@server ~]# bash /shell/chap05/while1.sh

示例2:猜商品价格,通过变量RANDOM获取随机整数并控制20以内,提示用户猜测商品价格,猜测时需要记录次数,猜中后退出程序。

bash 复制代码
[root@server ~]# vim /shell/chap05/while2.sh
#!/bin/bash

# RANDOM是一个环境变量,产生[1,32767]的整数,对20取余是控制随机数在1-19间
PRICE=$((RANDOM%20))
count=0

while true             # 恒真执行
do
        read  -p "请输入[1-20]间的商品价格: "  INT
        let count++
        if [ "$INT" -eq "$PRICE" ]
        then
                echo "恭喜,你猜对了!"
                echo  "你使用了$count次机会."
                break                       # 跳出while循环
        elif   [ "$INT" -gt "$PRICE" ]
        then
                echo  "你输入的商品价格高了."
        else
                echo  "你输入的商品价格低了."
        fi
done
[root@server ~]# bash /shell/chap05/while2.sh
请输入[1-20]间的商品价格: 3
你输入的商品价格低了.
请输入[1-20]间的商品价格: 5
恭喜,你猜对了!
你使用了2次机会.

示例3:逐行读取 ip.txt 文件里的 IP 地址,然后 ping 测试每个 IP 是否通。

bash 复制代码
[root@server ~]# cat > /shell/chap05/ip.txt <<EOF
192.168.168.1
192.168.168.2
192.168.168.3
8.8.8.8
www.baidu.com
EOF

[root@server ~]# vim /shell/chap05/while3.sh
#!/bin/bash

# 定义要读取的文件
FILE="/shell/chap05/ip.txt"

# while 循环逐行读取文件
cat $FILE | while read line
do
    # 输出当前读取的内容
    echo "正在检测:$line"

    # 执行 ping 命令
    ping -c 2 -w 3 $line &> /dev/null

    # 判断是否通
    if [ $? -eq 0 ];then
        echo "$line 可以连通"
    else
        echo "$line 无法连通"
    fi

    echo "-------------------------"
done
[root@server ~]# bash /shell/chap05/while3.sh
正在检测:192.168.168.1
192.168.168.1 可以连通
-------------------------
正在检测:192.168.168.2
192.168.168.2 可以连通
-------------------------
正在检测:192.168.168.3
192.168.168.3 无法连通
-------------------------
正在检测:8.8.8.8
8.8.8.8 可以连通
-------------------------
正在检测:www.baidu.com
www.baidu.com 可以连通
-------------------------

5.3 until循环

当条件成立则终止循环,条件不成立则执行循环中的语句。与while循环的执行条件相反

bash 复制代码
until 条件表达式
do
  command
done
#死循环:
until false
do
  command
done
bash 复制代码
[root@server ~]# vim /shell/chap05/until.sh
#!/bin/bash

i=1
until [  "$i" -gt 10 ]  # i>10 ,注意,条件要相反
do
        if id  test$i &> /dev/null
        then
                userdel  -r test$i
        else
                echo "test$i 账户已删除"
        fi
        let i++
done
[root@server ~]# bash /shell/chap05/until.sh

5.4 select循环

select循环语句的主要功能是创建菜单,在执行带有select循环语句脚本时,输出会按照数字顺序的列表显示一个菜单,并显示提示符(默认是#?),同时等待用户输入数字选择。

bash 复制代码
select 变量名  in 菜单值列表 
do
   statement1
   statement2
   ...
done

示例1:

bash 复制代码
[root@server ~]# vim /shell/chap05/select1.sh
#!/bin/bash

select mysql_version in 5.1 5.6
do
    echo $mysql_version
done

[root@server ~]# bash /shell/chap05/select1.sh
1) 5.1
2) 5.6
#? 1
5.1
#? 2
5.6

示例2:

bash 复制代码
[root@server ~]# vim /shell/chap05/select2.sh
#!/bin/bash
#设置提示符字符串
PS3='Choose your favorite fruit: '

select fruit in "Apples" "Bananas" "Pears" "Watermelons" "Grapes"
do
        echo
        echo "Your favorite fruit is $fruit."
        break
done
[root@server ~]# bash /shell/chap05/select2.sh
1) Apples
2) Bananas
3) Pears
4) Watermelons
5) Grapes
Choose your favorite fruit: 5

Your favorite fruit is Grapes.

5.5 循环控制

  • 跳出循环:
    • break:立即跳出当前循环
    • continue:跳出本次循环,立即开始下一次循环
  • 退出程序:exit

示例1:

bash 复制代码
#没有任何循环控制语句
[root@server ~]# vim /shell/chap05/test.sh
#!/bin/bash
for i in {1..2}
do
        for j in 11 22
        do
                for k in 111 222 333
                do
                        echo $k
                done
                echo $j
        done
        echo $i
done
[root@server ~]# bash /shell/chap05/test.sh
111
222
333
11
111
222
333
22
1
111
222
333
11
111
222
333
22
2
#添加break语句
[root@server ~]# vim  /shell/chap05/break1.sh
[root@server ~]# cat /shell/chap05/break1.sh
#!/bin/bash
for i in {1..2}
do
        for j in 11 22
        do
                for k in 111 222 333
                do
                        if [ "$k" -eq 222 ];then
                                break
                        fi
                        echo $k
                done
                echo $j
        done
        echo $i
done
[root@server ~]# bash /shell/chap05/break1.sh
111
11
111
22
1
111
11
111
22
2

#添加continue语句
[root@server ~]# vim /shell/chap05/continue1.sh
#!/bin/bash
for i in {1..2}
do
        for j in 11 22
        do
                for k in 111 222 333
                do
                        if [ "$k" -eq 222 ];then
                                continue
                        fi
                        echo $k
                done
                echo $j
        done
        echo $i
done
[root@server ~]# bash /shell/chap05/continue1.sh
111
333
11
111
333
22
1
111
333
11
111
333
22
2

#break后面有数字,跳出多层循环
[root@server ~]# vim /shell/chap05/break2.sh
#!/bin/bash
for i in {1..2}
do
        for j in 11 22
        do
                for k in 111 222 333
                do
                        if [ "$k" -eq 222 ];then
                                break 2
                        fi
                        echo $k
                done
                echo $j
        done
        echo $i
done
[root@server ~]# bash /shell/chap05/break2.sh
111
1
111
2
#continue后面有数字,继续第n层循环
[root@server ~]# vim /shell/chap05/continue2.sh
#!/bin/bash
for i in {1..2}
do
        for j in 11 22
        do
                for k in 111 222 333
                do
                        if [ "$k" -eq 222 ];then
                                continue 2
                        fi
                        echo $k
                done
                echo $j
        done
        echo $i
done

[root@server ~]# bash /shell/chap05/continue2.sh
111
111
1
111
111
2
#exit后面不管跟不跟数字,都会退出脚本,exit后面的数字表示脚本执行后的状态码
[root@server ~]# vim /shell/chap05/exit.sh
#!/bin/bash
for i in {1..2}
do
        for j in 11 22
        do
                for k in 111 222 333
                do
                        if [ "$k" -eq 222 ];then
                                exit 2
                        fi
                        echo $k
                done
                echo $j
        done
        echo $i
done

[root@server ~]# bash /shell/chap05/exit.sh
111
[root@server ~]# echo $?
2
相关推荐
fpcc1 小时前
Linux命令——lsof分析说明
linux·服务器
北京华盛恒辉软件开发公司11 小时前
大模型运维深远海漂浮式风电系统已融合人工智能AI软件平台
运维·人工智能
cui_ruicheng1 小时前
Linux网络编程(二):网络数据传输基本流程
linux·服务器·网络
怀旧,2 小时前
【Linux网络编程】15. Reactor 反应堆模式
linux·网络·php
汪汪大队u2 小时前
从 Docker Compose 到 Kubernetes:物联网管理系统迁移实战(3)—— 两个运维坑
运维·docker·kubernetes
小赵不会秃头2 小时前
数据结构Day 06:线性结构、库操作及 Makefile 完整学习笔记
java·linux·数据结构·算法·面试
雨田大大2 小时前
Windows11下IDEA运行后端时,端口被占用的解决方法
linux·运维·服务器
IKun-bug2 小时前
CentOS 7 安装 Claude Code 指南
linux·运维·centos
上海云盾-小余2 小时前
服务器入侵应急处置:痕迹清理、漏洞封堵与事后加固全流程
运维·服务器