shell脚本-循环

将某代码段重复运行多次,通常有进入循环的条件和退出循环的条件

重复运行次数

  • 循环次数事先已知
  • 循环次数事先未知

常见循环的命令:for,while,until

一、for循环

格式1:

for NAME [in WORDS ... ] ; do COMMANDS; done

for 变量名 [ in 列表 ]; do
    循环体
done

for 变量名 [ in 列表 ]
do
    循环体
done

执行机制:

  • 依次将列表中的元素赋值给“变量名”;每次赋值后即刻执行一次循环体;知道列表中的元素耗尽,循环结束
  • 如果省略[in WORDS ... ],此时使用位置参数变变量in "$@"

for循环列表生成方式:

  • 直接给出列表
  • 整数列表
    {start..end}
    $(seq [start [step]] end)
  • 返回列表的命令
    $(COMMAND)
  • 使用glob,如:*.sh
  • 变量引用,如:$@,$*,$#

例1,计算1+2+3+...+100结果:

[root@CentOS7 ~]# sum=0;for i in {1..100};do let sum+=$i;done ;echo sum=$sum
sum=5050
[root@CentOS7 ~]# seq -s+ 100|bc
5050

例2:

[root@CentOS7 ~]# cat for_sum.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-09
#FileName                     for_sum.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
sum=0
for i in $* ; do
    let sum+=$i
done
echo sum=$sum
[root@CentOS7 ~]# bash for_sum.sh 1 2 3 4 5 6
sum=21

例3,九九乘法表:

[root@CentOS7 ~]# cat haskell.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-09
#FileName                     haskell.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
for i in {1..9};do
    for j in `seq $i`;do
        echo -e "${j}x${i}=$[i*j]\t\c"
    done
    echo
done
[root@CentOS7 ~]# bash haskell.sh 
1x1=1    
1x2=2    2x2=4    
1x3=3    2x3=6    3x3=9    
1x4=4    2x4=8    3x4=12    4x4=16    
1x5=5    2x5=10    3x5=15    4x5=20    5x5=25    
1x6=6    2x6=12    3x6=18    4x6=24    5x6=30    6x6=36    
1x7=7    2x7=14    3x7=21    4x7=28    5x7=35    6x7=42    7x7=49    
1x8=8    2x8=16    3x8=24    4x8=32    5x8=40    6x8=48    7x8=56    8x8=64    
1x9=9    2x9=18    3x9=27    4x9=36    5x9=45    6x9=54    7x9=63    8x9=72    9x9=81
[root@CentOS7 ~]# cat haskell1.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-09
#FileName                     haskell1.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
for i in {1..9};do
    for j in `seq $i`;do
        let result=$[i*j]
        echo -e "${j}x${i}=$result\t\c"
    done
    echo
done
[root@CentOS7 ~]# bash haskell1.sh 
1x1=1    
1x2=2    2x2=4    
1x3=3    2x3=6    3x3=9    
1x4=4    2x4=8    3x4=12    4x4=16    
1x5=5    2x5=10    3x5=15    4x5=20    5x5=25    
1x6=6    2x6=12    3x6=18    4x6=24    5x6=30    6x6=36    
1x7=7    2x7=14    3x7=21    4x7=28    5x7=35    6x7=42    7x7=49    
1x8=8    2x8=16    3x8=24    4x8=32    5x8=40    6x8=48    7x8=56    8x8=64    
1x9=9    2x9=18    3x9=27    4x9=36    5x9=45    6x9=54    7x9=63    8x9=72    9x9=81

格式2:

for ((: for (( exp1; exp2; exp3 )); do COMMANDS; done

for ((控制变量初始化;条件判断表达式;控制变量的修正表达式));do
  循环体
done

注:

  • 控制变量初始化:仅在运行到循环代码段时执行一次
  • 控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断

shell脚本-循环

例:

[root@CentOS7 ~]# cat for_sum.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-09
#FileName                     for_sum.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
for ((sum=0,i=1;i<=100;i++)); do
        let sum+=i
done
echo sum=$sum
[root@CentOS7 ~]# bash for_sum.sh 
sum=5050
[root@CentOS7 ~]# cat for_sum.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-09
#FileName                     for_sum.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
for ((sum=0,i=1;i<=100;sum+=i,i++)); do
        true
done
echo $sum
[root@CentOS7 ~]# bash for_sum.sh 
5050

例2,九九乘法表:

[root@CentOS7 ~]# cat haskell2.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-09
#FileName                     haskell2.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
for ((i=1;i<10;i++));do
    for ((j=1;j<=i;j++));do
        echo -e "${j}x${i}=$((j*i))\t\c"
    done
    echo
done
[root@CentOS7 ~]# bash haskell2.sh 
1x1=1    
1x2=2    2x2=4    
1x3=3    2x3=6    3x3=9    
1x4=4    2x4=8    3x4=12    4x4=16    
1x5=5    2x5=10    3x5=15    4x5=20    5x5=25    
1x6=6    2x6=12    3x6=18    4x6=24    5x6=30    6x6=36    
1x7=7    2x7=14    3x7=21    4x7=28    5x7=35    6x7=42    7x7=49    
1x8=8    2x8=16    3x8=24    4x8=32    5x8=40    6x8=48    7x8=56    8x8=64    
1x9=9    2x9=18    3x9=27    4x9=36    5x9=45    6x9=54    7x9=63    8x9=72    9x9=81

二、while循环

格式:

while COMMANDS; do COMMANDS; done

while CONDITION; do
    循环体
done

注:

CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“TRUE”,执行一次循环;直到条件测试状态为“FALSE”终止循环,因此:CONDITION一般应该有循环控制变量;此变量的值会在循环体不断被修正

进入条件:CONDITION为TRUE

退出条件:CONDITION为FALSE

无限循环

while true; do
    循环体
done

例:

[root@CentOS7 ~]# cat while_sum.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-09
#FileName                     while_sum.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
i=1
sum=0
while [ $i -le 100 ];do
    let sum+=i
    let i++
done
echo sum=$sum
[root@CentOS7 ~]# bash while_sum.sh 
sum=5050

三、until循环

  工作逻辑与while类似,CONDITION为假,进行一次循环,CONDITION为真,退出循环

 格式:

until COMMANDS; do COMMANDS; done

until CONDITION; do
    循环体
done

说明:

  进入条件:CONDITION为FALSE(假)

  退出条件:CONDITION为TRUE(真)

无限循环

until false; do
    循环体
done

例1:

[root@CentOS7 ~]# cat until_sum.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-10
#FileName                     until_sum.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
i=1
sum=0
until [ ! $i -le 100 ]; do
    let sum+=i
    let i++
done
echo sum=$sum
[root@CentOS7 ~]# bash until_sum.sh 
sum=5050

四、循环控制语句continue

  continue [N],提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第一层

  格式:

while CONDITION1; do
    CMD1
    ...
    if CONDITION2; then
        continue [N]
    fi
    CMDn
    ...
done

例:

[root@CentOS7 ~]# cat continue.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-10
#FileName                     continue.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
for ((j=0;j<10;j++));do
    for((i=0;i<10;i++));do
        if [ $i -eq 5 ];then
            continue
        fi
        echo i=$i
    done
    echo j=$j
done
[root@CentOS7 ~]# bash continue.sh 
i=0
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
j=0
i=0
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
j=1
i=0
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
j=2
i=0
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
j=3
i=0
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
j=4
i=0
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
j=5
i=0
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
j=6
i=0
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
j=7
i=0
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
j=8
i=0
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
j=9
[root@CentOS7 ~]# cat continue.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-10
#FileName                     continue.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
for ((j=0;j<10;j++));do
    for((i=0;i<10;i++));do
        if [ $i -eq 5 ];then
            continue 2
        fi
        echo i=$i
    done
    echo j=$j
done
[root@CentOS7 ~]# bash continue.sh 
i=0
i=1
i=2
i=3
i=4
i=0
i=1
i=2
i=3
i=4
i=0
i=1
i=2
i=3
i=4
i=0
i=1
i=2
i=3
i=4
i=0
i=1
i=2
i=3
i=4
i=0
i=1
i=2
i=3
i=4
i=0
i=1
i=2
i=3
i=4
i=0
i=1
i=2
i=3
i=4
i=0
i=1
i=2
i=3
i=4
i=0
i=1
i=2
i=3
i=4

五、循环控制语句break

  break [N]:提前结束第N层整个循环,最内层为第1层

  格式:

while CONDITION1;do
    CMD1
    ...
    if CONDITION2; then
        break [N]
    fi
    CMDn
done

  例:

[root@CentOS7 ~]# cat break.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-10
#FileName                     continue.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
for ((j=0;j<10;j++));do
    for((i=0;i<10;i++));do
        if [ $i -eq 5 ];then
            break
        fi
        echo i=$i
    done
    echo j=$j
done
[root@CentOS7 ~]# bash break.sh 
i=0
i=1
i=2
i=3
i=4
j=0
i=0
i=1
i=2
i=3
i=4
j=1
i=0
i=1
i=2
i=3
i=4
j=2
i=0
i=1
i=2
i=3
i=4
j=3
i=0
i=1
i=2
i=3
i=4
j=4
i=0
i=1
i=2
i=3
i=4
j=5
i=0
i=1
i=2
i=3
i=4
j=6
i=0
i=1
i=2
i=3
i=4
j=7
i=0
i=1
i=2
i=3
i=4
j=8
i=0
i=1
i=2
i=3
i=4
j=9
[root@CentOS7 ~]# cat break.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-10
#FileName                     continue.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
for ((j=0;j<10;j++));do
    for((i=0;i<10;i++));do
        if [ $i -eq 5 ];then
            break 2
        fi
        echo i=$i
    done
    echo j=$j
done
[root@CentOS7 ~]# bash break.sh 
i=0
i=1
i=2
i=3
i=4

例:

[root@CentOS7 ~]# cat disk_check.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-12
#FileName                     disk_check.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
WARNING=80
while :;do
    USE=`df | sed -nr '/^\/dev/s#^([^ ]+).* ([0-9]+)%.*#\2#p' | sort -nr | head -1`
        if [ $USE -gt $WARNING ] ; then
            echo DISK will be full from `hostname -I` | mail -s "Disk Warning" 1074035975@qq.com
            break
        fi
    sleep 10
done
[root@CentOS7 ~]# bash disk_check.sh
[root@CentOS7 ~]#

shell脚本-循环

 

 

 

六、循环控制shift命令

  shift [n]用于将参数列表list左移指定次数,缺省为左移一次。

  参数列表list一旦被移动,最左端的那个参数就从列表中删除。while循环遍历位置参数列表时,常用到shift

  例:

[root@CentOS7 ~]# cat create_user.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-10
#FileName                     create_user.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
while [ "$1" ];do
    id $1 &> /dev/null || { useradd $1 ; echo $1 is created; }
    shift
done
[root@CentOS7 ~]# bash create_user.sh u1 u2 u3
u1 is created
u2 is created
u3 is created

七、while read 特殊用法

while 循环的特殊用法,遍历文件或文本的每一行;逐行处理时使用while read

格式:

while read line; do
    循环体
done < /PATH/FROM/SOMEFILE

注:依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量line

例:

[root@CentOS7 ~]# seq 10
1
2
3
4
5
6
7
8
9
10
[root@CentOS7 ~]# seq 10 > a.txt
[root@CentOS7 ~]# echo user{1..10} | xargs -n1
user1
user2
user3
user4
user5
user6
user7
user8
user9
user10
[root@CentOS7 ~]# echo user{1..10} | xargs -n1 > user.txt
[root@CentOS7 ~]# paste -d' ' a.txt user.txt > users.txt
[root@CentOS7 ~]# cat users.txt 
1 user1
2 user2
3 user3
4 user4
5 user5
6 user6
7 user7
8 user8
9 user9
10 user10
[root@CentOS7 ~]# cat while_read.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-12
#FileName                     while_read.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
while read id name;do
    echo -e "id=$id\tname=$name"
done < users.txt
[root@CentOS7 ~]# bash while_read.sh 
id=1    name=user1
id=2    name=user2
id=3    name=user3
id=4    name=user4
id=5    name=user5
id=6    name=user6
id=7    name=user7
id=8    name=user8
id=9    name=user9
id=10    name=user10

例1-硬盘大于百分之80发送报警邮件(无限循环):

[root@CentOS7 ~]# cat disk_check.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-12
#FileName                     disk_check.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
while :;do
    df | sed -nr '/^\/dev/s#^([^ ]+).* ([0-9]+)%.*#\2 \1#p' | while read use dev; do
        [ $use -gt 80 ] && echo "$dev will be full,use: $use" | mail -s "Disk Warning" 1074035975@qq.com
    done
    sleep 10
done
[root@CentOS7 ~]# bash disk_check.sh 
^C
[root@CentOS7 ~]#
[root@CentOS7 ~]# cp /dev/zero /boot/disk.img
cp: error writing ‘/boot/disk.img’: No space left on device
cp: failed to extend ‘/boot/disk.img’: No space left on device
[root@CentOS7 ~]# df
Filesystem              1K-blocks    Used Available Use% Mounted on
devtmpfs                   919504       0    919504   0% /dev
tmpfs                      931512       0    931512   0% /dev/shm
tmpfs                      931512   17984    913528   2% /run
tmpfs                      931512       0    931512   0% /sys/fs/cgroup
/dev/mapper/centos-root 104806400 4807772  99998628   5% /
/dev/sda1                 1038336 1038276        60 100% /boot
/dev/mapper/centos-data  52403200  227600  52175600   1% /data
tmpfs                      186304       0    186304   0% /run/user/0

shell脚本-循环

 

 

 例2-硬盘大于百分之80发送报警邮件(循环一次):

[root@CentOS7 ~]# cat disk_check.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-12
#FileName                     disk_check.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
WRNING=80
USE1=`df | sed -nr '/^\/dev/s#^([^ ]+).* ([0-9]+)%.*#\2#p' | sort -nr | head -1`
while :; do
    USE=`df | sed -nr '/^\/dev/s#^([^ ]+).* ([0-9]+)%.*#\2#p' | sort -nr | head -1`
    if [ $USE -gt $WRNING ];then
        df | sed -nr '/^\/dev/s#^([^ ]+).* ([0-9]+)%.*#\2 \1#p' | while read use dev;do
            [ $use -gt 80 ] && echo "$dev will be full,use:$use" | mail -s "Disk Warning" 1074035975@qq.com
        done
    echo "USE1=$USE1,use=$use,dev=$dev,WRNING=$WRNING,USE=$USE"
    break
    fi
    sleep 10
done
[root@CentOS7 ~]# df
Filesystem              1K-blocks    Used Available Use% Mounted on
devtmpfs                   919504       0    919504   0% /dev
tmpfs                      931512       0    931512   0% /dev/shm
tmpfs                      931512   17984    913528   2% /run
tmpfs                      931512       0    931512   0% /sys/fs/cgroup
/dev/mapper/centos-root 104806400 4807440  99998960   5% /
/dev/sda1                 1038336  153668    884668  15% /boot
/dev/mapper/centos-data  52403200  227600  52175600   1% /data
tmpfs                      186304       0    186304   0% /run/user/0
[root@CentOS7 ~]# bash disk_check.sh 
USE1=15,use=,dev=,WRNING=80,USE=100
[root@CentOS7 ~]# df
Filesystem              1K-blocks    Used Available Use% Mounted on
devtmpfs                   919504       0    919504   0% /dev
tmpfs                      931512       0    931512   0% /dev/shm
tmpfs                      931512   17984    913528   2% /run
tmpfs                      931512       0    931512   0% /sys/fs/cgroup
/dev/mapper/centos-root 104806400 4807440  99998960   5% /
/dev/sda1                 1038336 1038276        60 100% /boot
/dev/mapper/centos-data  52403200  227600  52175600   1% /data
tmpfs                      186304       0    186304   0% /run/user/0

shell脚本-循环

 

 

 八、select循环与菜单

  格式:

select NAME [in WORDS ... ;] do COMMANDS; done

select variable in list ;do
    循环体命令
done

  说明:

  • select循环主要用于创建菜单,按数字顺序排列的菜单项显示在标准错误上,并显示PS3提示符,等待用户输入
  • 用户输入菜单列单中的某个数字,执行相应的命令
  • 用户输入被保存在内置变量REPLY中
  • select是个无限循环,因此要用break命令退出循环,或用exit命令终止脚本。也可以按Ctrl+c退出循环
  • select经常和case联合使用
  • 与for循环类似,可以省略in list,此时使用位置参量

例:

[root@CentOS7 ~]# cat select.sh 
#!/bin/bash
#
#*************************************************************************************
#Author:                      wanghaomiao
#QQ:                          1074035975
#Date:                        2022-01-12
#FileName                     select.sh
#URL:                         www.wanghaomiao.com.cn
#Description:                 The test script
#Copyreght (C):               2022 All rightsreserved
#*************************************************************************************
sum=0
PS3="请点菜(1-6): "
select MENU in 北京烤鸭 佛跳墙 小龙虾 羊蝎子 火锅 点菜结束;do
case $REPLY in
1)
    echo $MENU 价格是 100
    let sum+=100
    ;;
2)
    echo $MENU 价格是 88
    let sum+=88
    ;;
3)
    echo $MENU 价格是 66
    let sum+=66
    ;;
4)
    echo $MENU 价格是 166
    let sum+=166
    ;;
5)
    echo $MENU 价格是 200
    let sum+=200
    ;;
6)
    echo "点菜结束,退出"
    break
    ;;
*)
    echo "输入错误,请重新选择"
    ;;
esac
done
echo "总价格是:$sum"
[root@CentOS7 ~]# bash select.sh 
1) 北京烤鸭
2) 佛跳墙
3) 小龙虾
4) 羊蝎子
5) 火锅
6) 点菜结束
请点菜(1-6): 1
北京烤鸭 价格是 100
请点菜(1-6): 4
羊蝎子 价格是 166
请点菜(1-6): 5
火锅 价格是 200
请点菜(1-6): 6
点菜结束,退出
总价格是:466
[root@CentOS7 ~]#

 

上一篇:Docker部署微服务遇到问题总结


下一篇:05 UCI