SHELL脚本编程循环篇-while循环

              SHELL脚本编程循环篇-while循环

                                          作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

一.while循环的语法格式

while CONDITION; do
  循环体
done


以上参数关键点说明:
  CONDITION:
    循环控制条件,进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“true”,则执行一次循环;直到条件测试状态为“false”终止循环。因此,CONDTION一般应该有循环控制变量;而此变量的值会在循环体不断地被修正
  进入条件:
    CONDITION为true
  退出条件:
    CONDITION为false

其实也可以写成一行:
  [root@node101.yinzhengjie.org.cn ~]# i=1;while [ $i -le 100 ];do let sum+=i;let i++;done;echo sum=$sum
  sum=5050
  [root@node101.yinzhengjie.org.cn ~]#

二.循环控制语句continue

while CONDTIITON1; do
  CMD1
  ...
  if CONDITION2; then
    continue
  fi
  CMDn
  ...
done


使用场景:
  用于循环体中,continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第1层
[root@node101.yinzhengjie.org.cn ~]# cat shell/continue.sh
#!/bin/bash
#
#********************************************************************
#Author:        yinzhengjie
#QQ:             1053419035
#Date:             2019-11-25
#FileName:        shell/continue.sh
#URL:             http://www.cnblogs.com/yinzhengjie
#Description:        The test script
#Copyright notice:     original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************

flag=true

i=0

while [ $i -lt 10 ];do
    let i++
    #如果"$i"的值为7,则跳过本次循环进行下一次循环
    if [ $i -eq 7 ];then 
        continue
    fi
    echo $i
done
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# bash shell/continue.sh
1
2
3
4
5
6
8
9
10
[root@node101.yinzhengjie.org.cn ~]# 
案例展示
[root@node101.yinzhengjie.org.cn ~]# cat shell/continue.sh 
#!/bin/bash
#
#********************************************************************
#Author:        yinzhengjie
#QQ:             1053419035
#Date:             2019-11-25
#FileName:        shell/continue.sh
#URL:             http://www.cnblogs.com/yinzhengjie
#Description:        The test script
#Copyright notice:     original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************

flag=true

i=0

while [ $i -lt 3 ];do
    let i++
    for((j=1;j<=10;j++));do
        if [ $j -eq 7 ];then 
            #退出到本层循环的上一轮循环
            continue 2
        fi
        echo j=$j
    done
    echo i=$i
done
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# bash shell/continue.sh 
j=1
j=2
j=3
j=4
j=5
j=6
j=1
j=2
j=3
j=4
j=5
j=6
j=1
j=2
j=3
j=4
j=5
j=6
[root@node101.yinzhengjie.org.cn ~]# 
案例展示2

三.循环控制语句break

while CONDTIITON1; do
  CMD1
  ...
  if CONDITION2; then
    break
  fi
  CMDn
  ...
done

使用场景:   用于循环体中,break [N]:提前结束第N层循环,最内层为第1层
[root@node101.yinzhengjie.org.cn ~]# cat shell/break.sh 
#!/bin/bash
#
#********************************************************************
#Author:        yinzhengjie
#QQ:             1053419035
#Date:             2019-11-25
#FileName:        shell/continue.sh
#URL:             http://www.cnblogs.com/yinzhengjie
#Description:        The test script
#Copyright notice:     original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************

flag=true

i=0

while [ $i -lt 10 ];do
    let i++
    #如果"$i"的值为7,则直接跳出循环
    if [ $i -eq 7 ];then 
        break
    fi
    echo $i
done
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# bash shell/break.sh 
1
2
3
4
5
6
[root@node101.yinzhengjie.org.cn ~]# 
案例展示1
[root@node101.yinzhengjie.org.cn ~]# cat shell/break.sh 
#!/bin/bash
#
#********************************************************************
#Author:        yinzhengjie
#QQ:             1053419035
#Date:             2019-11-25
#FileName:        shell/continue.sh
#URL:             http://www.cnblogs.com/yinzhengjie
#Description:        The test script
#Copyright notice:     original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************

flag=true

i=0

while [ $i -lt 3 ];do
    let i++
    for((j=1;j<=10;j++));do
        if [ $j -eq 7 ];then 
            #退出本层循环的上一层循环
            break 2
        fi
        echo j=$j
    done
    echo i=$i
done
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# bash shell/break.sh 
j=1
j=2
j=3
j=4
j=5
j=6
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# 
案例展示2

四.循环控制shift命令

shift [n]:
  用于将参量列表 list 左移指定次数,缺省为左移一次。   参量列表 list 一旦被移动,最左端的那个参数就从列表中删除。
while 循环遍历位置参量列表时,常用到 shift
[root@node101.yinzhengjie.org.cn ~]# cat shell/useradd.sh
#!/bin/bash
#
#********************************************************************
#Author:        yinzhengjie
#QQ:             1053419035
#Date:             2019-11-25
#FileName:        shell/useradd.sh
#URL:             http://www.cnblogs.com/yinzhengjie
#Description:        The test script
#Copyright notice:     original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************

echo 1st arg is $1
echo 2st arg is $2
echo all args are $*
shift

echo shift
echo 1st arg is $1
echo 2st arg is $2
echo all args are $*
shift

echo shift
echo 1st arg is $1
echo 2st arg is $2
echo all args are $*


[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# bash shell/useradd.sh a b c d e f g
1st arg is a
2st arg is b
all args are a b c d e f g
shift
1st arg is b
2st arg is c
all args are b c d e f g
shift
1st arg is c
2st arg is d
all args are c d e f g
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# 
案例展示1
[root@node101.yinzhengjie.org.cn ~]# cat shell/useradd.sh
#!/bin/bash
#
#********************************************************************
#Author:        yinzhengjie
#QQ:             1053419035
#Date:             2019-11-25
#FileName:        shell/useradd.sh
#URL:             http://www.cnblogs.com/yinzhengjie
#Description:        The test script
#Copyright notice:     original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************

while true;do
    [ -z "$1" ] && break
    useradd $1 && echo "$1 is created."
    shift
done
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# bash shell/useradd.sh a b c d e
a is created.
b is created.
c is created.
d is created.
e is created.
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# tail -5 /etc/passwd
a:x:1044:1044::/home/a:/bin/bash
b:x:1045:1045::/home/b:/bin/bash
c:x:1046:1046::/home/c:/bin/bash
d:x:1047:1047::/home/d:/bin/bash
e:x:1048:1048::/home/e:/bin/bash
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# 
参考案例2
[root@node101.yinzhengjie.org.cn ~]# vim shell/doit.sh
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# cat shell/doit.sh
#!/bin/bash
#
#********************************************************************
#Author:        yinzhengjie
#QQ:             1053419035
#Date:             2019-11-25
#FileName:        shell/useradd.sh
#URL:             http://www.cnblogs.com/yinzhengjie
#Description:        The test script
#Copyright notice:     original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************

while [ $# -gt 0 ] # 也可以写出C语言风格:(( $# > 0 ))
do
   echo $*
   shift
done
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# bash shell/doit.sh {a..z}
a b c d e f g h i j k l m n o p q r s t u v w x y z
b c d e f g h i j k l m n o p q r s t u v w x y z
c d e f g h i j k l m n o p q r s t u v w x y z
d e f g h i j k l m n o p q r s t u v w x y z
e f g h i j k l m n o p q r s t u v w x y z
f g h i j k l m n o p q r s t u v w x y z
g h i j k l m n o p q r s t u v w x y z
h i j k l m n o p q r s t u v w x y z
i j k l m n o p q r s t u v w x y z
j k l m n o p q r s t u v w x y z
k l m n o p q r s t u v w x y z
l m n o p q r s t u v w x y z
m n o p q r s t u v w x y z
n o p q r s t u v w x y z
o p q r s t u v w x y z
p q r s t u v w x y z
q r s t u v w x y z
r s t u v w x y z
s t u v w x y z
t u v w x y z
u v w x y z
v w x y z
w x y z
x y z
y z
z
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# 
参考案例3

五.while循环的特殊用法(遍历文件的每一行)

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

以上语法作用说明:   依次读取
/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量line
[root@node101.yinzhengjie.org.cn ~]# while read line;do echo $line;done < /etc/fstab 

#
# /etc/fstab
# Created by anaconda on Mon Jul 8 16:22:49 2019
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/centos-root / xfs defaults 0 0
UUID=343e9f9c-8324-4918-a10d-541627af8e04 /boot xfs defaults 0 0
/dev/mapper/centos-home /home xfs defaults 0 0
/dev/mapper/centos-swap swap swap defaults 0 0
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# 
参考案例1
[root@node101.yinzhengjie.org.cn ~]# cat shell/whileread.sh
#!/bin/bash
#
#********************************************************************
#Author:        yinzhengjie
#QQ:             1053419035
#Date:             2019-11-25
#FileName:        shell/whileread.sh
#URL:             http://www.cnblogs.com/yinzhengjie
#Description:        The test script
#Copyright notice:     original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************

while read line;do
   uid=`echo $line |cut -d : -f 3`
   username=`echo $line |cut -d : -f 1`
   if [ $uid -ge 1000 ];then
       echo $username:$uid
   fi
done < /etc/passwd
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# bash shell/whileread.sh
mysql:1000
yinzhengjie:1001
jason:1002
jason1:1003
jason2:1004
jason3:1005
jason4:1006
jason5:1007
jason6:1008
jason7:1009
jason8:1010
jason9:1011
jason10:1012
jason11:1013
jason12:1014
jason13:1015
jason14:1016
jason15:1017
jason16:1018
jason17:1019
jason18:1020
jason19:1021
jason20:1022
jason21:1023
jason22:1024
jason23:1025
jason24:1026
jason25:1027
jason26:1028
jason27:1029
jason28:1030
jason29:1031
jason30:1032
yinzhengjie1:1033
yinzhengjie2:1034
yinzhengjie3:1035
yinzhengjie4:1036
yinzhengjie5:1037
yinzhengjie6:1038
yinzhengjie7:1039
yinzhengjie8:1040
yinzhengjie9:1041
yinzhengjie10:1042
cracker:1043
a:1044
b:1045
c:1046
d:1047
e:1048
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# 
参考案例2
[root@node101.yinzhengjie.org.cn ~]# cat shell/check_disk.sh
#!/bin/bash
#
#********************************************************************
#Author:        yinzhengjie
#QQ:             1053419035
#Date:             2019-11-25
#FileName:        shell/check_disk.sh
#URL:             http://www.cnblogs.com/yinzhengjie
#Description:        The test script
#Copyright notice:     original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************

warning=10

df | while read diskspace;do
    space=`echo $diskspace | sed -nr '/^/dev/sd/s#.* (.+)%.*#1#p'`
    disk=`echo $diskspace | sed -nr '/^/dev/sd/s#([^ ]+).*#1#p'`
    if [[ $space =~ ^[0-9+$] ]];then
        if [ $space -gt $warning ];then
        echo $disk:$space
    fi
    fi
done
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# bash shell/check_disk.sh
/dev/sda1:15
[root@node101.yinzhengjie.org.cn ~]# 
参考案例3(磁盘使用空间监控脚本)
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# cat shell/ddos.sh
#!/bin/bash
#
#********************************************************************
#Author:        yinzhengjie
#QQ:             1053419035
#Date:             2019-11-25
#FileName:        shell/ddos.sh
#URL:             http://www.cnblogs.com/yinzhengjie
#Description:        The test script
#Copyright notice:     original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************

netstat -nta | sed -nr '/^tcp /s/.*  ([1-9].*):.*/1/p' | sort| uniq -c | while read iplist;do
    linknum=`echo $iplist | cut -d " " -f 1`
    ip=`echo $iplist | cut -d " " -f 2`
    if [ $linknum -ge 2 ];then
        echo $ip >> /root/cracker_ip.log
    fi
done
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# bash shell/ddos.sh
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# cat cracker_ip.log 
172.30.1.254
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]#
参考案例4(防止DDOS共计的方法)

六.请用while循环实现以下小练习

1>.计算1到100之间的和

[root@node101.yinzhengjie.org.cn ~]# cat shell/sum.sh 
#!/bin/bash
#
#********************************************************************
#Author:        yinzhengjie
#QQ:             1053419035
#Date:             2019-11-25
#FileName:        shell/sum.sh
#URL:             http://www.cnblogs.com/yinzhengjie
#Description:        The test script
#Copyright notice:     original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************

sum=0
read -t 30 -p "Please enter the start number>>> " StartNumber
read -t 30 -p "Please enter an end number>>> " EndNumber

while [ $StartNumber -le $EndNumber ]
    do
        sum=$(( $sum + $StartNumber ))
        StartNumber=$(( $StartNumber + 1 ))
done

StartNumber=$(( $StartNumber - $EndNumber ))

echo "从$StartNumber加到$EndNumber的总和是:$sum"
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# bash shell/sum.sh 
Please enter the start number>>> 1
Please enter an end number>>> 100
从1加到100的总和是:5050
[root@node101.yinzhengjie.org.cn ~]# 

2>.若有人使用"yinzhengjie"用户登录则立即踢出它并将其IP拉入黑名单,以防止该用户继续使用该IP地址进行登录。

[root@node101.yinzhengjie.org.cn ~]# cat shell/scan_cracker.sh
#!/bin/bash
#
#********************************************************************
#Author:        yinzhengjie
#QQ:             1053419035
#Date:             2019-11-25
#FileName:        shell/scan_cracker.sh
#URL:             http://www.cnblogs.com/yinzhengjie
#Description:        The test script
#Copyright notice:     original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************

while true;do
    #获取使用"yinzhengjie"用户登录的IP地址
    iplist=`who | sed -nr '/^yinzhengjie/s/.*((.*))/1/p'`
    #判断当前使用有人使用"yinzhengjie"用户登录
    if [ "$iplist" ];then
        #若使用"yinzhengjie"用户登录成功就直接剔除掉该用户
        pkill -9 -U yinzhengjie
        echo "cracker is killed"
    #将刚刚使用"yinzhengjie"用户的IP地址加入黑名单,以防止该用户再次登录。
        echo sshd:$iplist >> /etc/hosts.deny
    fi
    sleep 10
done
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# bash shell/scan_cracker.sh        #运行该脚本后使用"yinzhengjie"用户登录测试,观察相关的配置文件及输出信息。
cracker is killed
^C
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# cat /etc/hosts.deny 
#
# hosts.deny    This file contains access rules which are used to
#        deny connections to network services that either use
#        the tcp_wrappers library or that have been
#        started through a tcp_wrappers-enabled xinetd.
#
#        The rules in this file can also be set up in
#        /etc/hosts.allow with a 'deny' option instead.
#
#        See 'man 5 hosts_options' and 'man 5 hosts_access'
#        for information on rule syntax.
#        See 'man tcpd' for information on tcp_wrappers
#
sshd:172.30.1.254
[root@node101.yinzhengjie.org.cn ~]# 
参考案例

3>.编写脚本,求100以内所有正奇数之和

4>.编写脚本,提示请输入网络地址,如192.168.0.0,判断输入的网段中主机在线状态,并统计在线和离线主机各多少


5>.编写脚本,打印九九乘法表


6>.编写脚本,利用变量RANDOM生成10个随机数字,输出这个10数字,并显示其中的最大值和最小值


7>.编写脚本,实现打印国际象棋棋盘


8>.后续六个字符串:efbaf275cd、4be9c40b8b、44b2395c46、f8c8873ce0、b902c16c8b、ad865d2f63是通过对随机数变量RANDOM随机执行命令: echo $RANDOM|md5sum|cut –c1-10 后的结果,请破解这些字符串对应的RANDOM值

9>.编写脚本,将最近登录失败的IP统计出来并保存在配置文件中

[root@node101.yinzhengjie.org.cn ~]# cat shell/check_lastb.sh
#!/bin/bash
#
#********************************************************************
#Author:        yinzhengjie
#QQ:             1053419035
#Date:             2019-11-25
#FileName:        shell/check_lastb.sh
#URL:             http://www.cnblogs.com/yinzhengjie
#Description:        The test script
#Copyright notice:     original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************

localnet="172.30.1"  
sleeptime=10

while true;do
    #使用"lastb"命令来查看最近登录服务器失败的信息,并将非"$localnet"网段的IP过滤出来。
    iplist=`lastb | grep -Eo "(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"|grep -v "$
localnet" |sort -u`    #此处不要对"$iplist"加引号,因为加了引号后会把所有的IP地址当作一个整体来使用了,我们需要的是没有IP单独一行
    for ip in $iplist;do
        #判断当前ip是否已经写入文件,若没有则写入,若能找到就短路或了.
        grep "$ip" /root/crack_iplist.log &> /dev/null || echo "$ip" >> /root/crack_iplist.log
    done
    sleep $sleeptime
done
[root@node101.yinzhengjie.org.cn ~]# 
[root@node101.yinzhengjie.org.cn ~]# 
参考案例

 

原文地址:https://www.cnblogs.com/yinzhengjie/p/9158207.html