将某代码段重复运行多次,通常有进入循环的条件和退出循环的条件
重复运行次数
- 循环次数事先已知
- 循环次数事先未知
常见循环的命令: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
注:
- 控制变量初始化:仅在运行到循环代码段时执行一次
- 控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断
例:
[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 ~]#
六、循环控制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
例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
八、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 ~]#