zoukankan      html  css  js  c++  java
  • shell 学习笔记9-while/until循环语句

    一、while循环语句

      1、循环语句

        循环愈久就是重复执行一条指令或一组执行,知道条件不在满足时停止,shell循环语句包括,while、until、for、select语句

      2、while循环

        主要用来重复执行命令或语句,常用来守护进程或持续运行的程序,其实大多数循环都会用for循环语句

      3、语法

    while <条件表达式>
    do
        指令...
    done

       4、流程图

    二、until循环语句

      1、until循环语句语法

    until <条件表达式>
    do
        指令...
    done

      until 循环语句用法与while类似,只是until会在表达式不成立时,进入循环执行命令,表达式成立,终止循环,until应用场景非常罕见

    三、知识补充

      1、当型和直型循环的范例

        shell中有两个休息命令:sleep 1 表示休息1秒,usleep 1000000 也表示休息1秒

        1)每隔2秒输出一次系统负载

    [root@web1 scripts]# ./test
    test10.sh    test14.sh    test19.sh    test22.sh    test27.sh    test31.sh    test36.sh    test7.sh
    test11.sh    test15.sh    test1.sh     test23.sh    test28.sh    test32.sh    test3.sh     test8.sh
    test12-1.sh  test16.sh    test20.sh    test24.sh    test29.sh    test33.sh    test4.sh     test9.sh
    test12.sh    test17.sh    test21-1.sh  test25.sh    test2.sh     test34.sh    test5.sh     
    test13.sh    test18.sh    test21.sh    test26.sh    test30.sh    test35.sh    test6.sh     
    [root@web1 scripts]# cat test36.sh
    #!/bin/bash
    while true            #while true 表示条件永远为真,就像是死循环一样,我们称为守护进程
    do
            uptime        
            sleep 2         #休息2秒,在继续循环,while true循环中最好添加类似sleep的命令,可以控制脚本频率,省资源,不然真成死循环了
    done
    [root@web1 scripts]# ./test36.sh 
     12:26:45 up 10 days,  1:50,  3 users,  load average: 0.00, 0.01, 0.05
     12:26:47 up 10 days,  1:50,  3 users,  load average: 0.00, 0.01, 0.05
     12:26:49 up 10 days,  1:51,  3 users,  load average: 0.00, 0.01, 0.05

        2)每隔2秒在屏幕上输出一次负载并将负载值追加到log里,使用微秒单位

    [root@web1 scripts]# cat test37.sh 
    #!/bin/bash
    while [ 1 ]
    do
            uptime >>/tmp/uptime.log
            usleep 2000000
    done
    [root@web1 scripts]# ./test37.sh
    ^C
    [root@web1 scripts]# cat /tmp/uptime.log 
     12:31:41 up 10 days,  1:55,  3 users,  load average: 0.00, 0.01, 0.05
     12:31:43 up 10 days,  1:55,  3 users,  load average: 0.00, 0.01, 0.05
     12:31:45 up 10 days,  1:55,  3 users,  load average: 0.00, 0.01, 0.05
     12:31:47 up 10 days,  1:55,  3 users,  load average: 0.00, 0.01, 0.05
     12:31:49 up 10 days,  1:56,  3 users,  load average: 0.00, 0.01, 0.05
     12:31:51 up 10 days,  1:56,  3 users,  load average: 0.00, 0.01, 0.05
     12:31:53 up 10 days,  1:56,  3 users,  load average: 0.00, 0.01, 0.05
     12:31:55 up 10 days,  1:56,  3 users,  load average: 0.00, 0.01, 0.05
     12:31:57 up 10 days,  1:56,  3 users,  load average: 0.00, 0.01, 0.05
     12:31:59 up 10 days,  1:56,  3 users,  load average: 0.00, 0.01, 0.05
     12:32:01 up 10 days,  1:56,  3 users,  load average: 0.00, 0.01, 0.05
     12:32:03 up 10 days,  1:56,  3 users,  load average: 0.00, 0.01, 0.05
     12:32:05 up 10 days,  1:56,  3 users,  load average: 0.00, 0.01, 0.05
     12:32:07 up 10 days,  1:56,  3 users,  load average: 0.00, 0.01, 0.05
     12:32:09 up 10 days,  1:56,  3 users,  load average: 0.00, 0.01, 0.05
     12:32:11 up 10 days,  1:56,  3 users,  load average: 0.00, 0.01, 0.05
     12:32:13 up 10 days,  1:56,  3 users,  load average: 0.00, 0.01, 0.05

        3)通过结尾使用&符合后台运行脚本

    [root@web1 scripts]# ./test37.sh &
    [1] 19536
    [root@web1 scripts]# tail -f /tmp/uptime.log
     12:46:07 up 10 days,  2:10,  3 users,  load average: 0.00, 0.01, 0.05
     12:46:09 up 10 days,  2:10,  3 users,  load average: 0.00, 0.01, 0.05
     12:46:11 up 10 days,  2:10,  3 users,  load average: 0.00, 0.01, 0.05
     12:46:14 up 10 days,  2:10,  3 users,  load average: 0.00, 0.01, 0.05
     12:46:16 up 10 days,  2:10,  3 users,  load average: 0.00, 0.01, 0.05
     12:46:18 up 10 days,  2:10,  3 users,  load average: 0.00, 0.01, 0.05
     12:46:20 up 10 days,  2:10,  3 users,  load average: 0.00, 0.01, 0.05
     12:46:22 up 10 days,  2:10,  3 users,  load average: 0.00, 0.01, 0.05
     12:46:24 up 10 days,  2:10,  3 users,  load average: 0.00, 0.01, 0.05
     12:46:26 up 10 days,  2:10,  3 users,  load average: 0.00, 0.01, 0.05
     12:46:28 up 10 days,  2:10,  3 users,  load average: 0.00, 0.01, 0.05

      2、shell脚本后台运行的知识补充

        1)用法及说明

     

    [root@web1 scripts]# ./test37.sh &        #后台运行脚本
    [2] 32970
    [1]   Terminated              ./test37.sh
    [root@web1 scripts]# fg           #将脚本放到前台执行,如果多脚本任务,可以使用fg加jobs输出的任务编号调出相应的脚本到前台
    ./test37.sh
    ^Z                        #使用ctrl+z快捷键,暂停脚本
    [2]+  Stopped                 ./test37.sh
    [root@web1 scripts]# bg            #bg,将当前执行的脚本放到后台运行
    [2]+ ./test37.sh &
    [root@web1 scripts]# jobs          #查看任务
    [2]+  Running                 ./test37.sh &       
    
    [root@web1 scripts]# fg 2          #fg加jobs输出的任务号调出脚本到前台来运行
    ./test37.sh
    ^C
    [root@web1 scripts]# jobs          
    [root@web1 scripts]# ./test37.sh &
    [1] 33054
    [root@web1 scripts]# jobs
    [1]+  Running                 ./test37.sh &
    [root@web1 scripts]# kill %1        #kill 命令关闭jobs任务脚本
    [root@web1 scripts]# jobs
    [1]+  Terminated              ./test37.sh
    [root@web1 scripts]# 

    四、范例

      1、使用while循环竖向打印54321

    [root@web1 scripts]# cat test38.sh
    #!/bin/bash
    i=5                        #因为是从大到小,所以初始化i的值为5
    while ((i>0))                  #双小括号条件表达式,当i大于0不成立时就跳出循环
    do 
            echo "$i"                #打印变量i的值
            ((i--))                 #i的值自减,每次减1
    done
    
    [root@web1 scripts]# ./test38.sh 
    5
    4
    3
    2
    1
    [root@web1 scripts]# 

      2、使用双中括号条件表达式

    [root@web1 while-until]# cat test39.sh 
    #!/bin/bash
    i=5
    while [[ $i > 0 ]]
    do
            echo $i
            ((i--))
    done
    
    [root@web1 while-until]# ./test39.sh 
    5
    4
    3
    2
    1
    [root@web1 while-until]# 

      3、使用传参需要打印的数字

    [root@web1 while-until]# cat test40.sh 
    #!/bin/bash
    
    i="$1"
    while [[ $i -gt 0 ]]
    do 
            echo $i
            ((i--))
    done
    
    [root@web1 while-until]# ./test40.sh  5
    5
    4
    3
    2
    1
    [root@web1 while-until]# 

      4、使用until语句实现

    [root@web1 while-until]# cat test41.sh
    #!/bin/bash
    i=5
    until [[ $i < 1 ]]        #当条件表达式不成立时,进入循环执行命令,因为0<1成立,因此退出循环
    do
            echo $i
            ((i--))
    done
    [root@web1 while-until]# ./test41.sh  
    5
    4
    3
    2
    1
    [root@web1 while-until]# 

      5、计算1加到100之和

    [root@web1 while-until]# cat test42.sh 
    #!/bin/bash
    i=1                             #i为自增变量,从1到100,初始值1
    sum=0                            #总和变量初始值为0
    while ((i<=100))                     #条件是i小于等于100,也就是从1加到100
    do
            ((sum=sum+i))                  #把i的值和当前sum总和的值做加法结果重新赋值给sum
            ((i++))                      #i每次加1
    done
    [ "$sum" -ne 0 ] && printf "totalsum is:$sum
    "
     
    [root@web1 while-until]# ./test42.sh 
    totalsum is:5050
    [root@web1 while-until]# 

      6、通过数学公式实现

    [root@web1 while-until]# cat 4-6.sh 
    #!/bin/bash
    i=100
    ((sum=i*(i+1)/2))              #利用数公式求和公式计算,效率很高
    echo $sum
    
    [root@web1 while-until]# ./4-6.sh 
    5050

      7、猜数字游戏

    #!/bin/bash
    total=0
    export LANG="zh_CN.UTF-8"
    NUM=$((RANDOM%61))
    echo "当前苹果价格是每斤$NUM元"
    echo "========================"
    usleep 1000000
    clear
    echo '这苹果多少钱一斤啊?
          请猜0-60的数字'
    apple(){
    read -p "请输入你的价格:" PRICE
    expr $PRICE + 1 &>/dev/null
    if [ $? -ne 0 ]
     then
            echo "别逗我了,快猜数字"
            apple
    fi
    }
    
    guess(){
            ((total++))
            if [ $PRICE -eq $NUM ]
             then
                    echo "猜对了,就是$NUM元"
                    if [ $total -le 3 ];then
                       echo "一共猜了$total次,太牛了。"
                    elif [ $total -gt 3 -a $total -le 6 ];then
                       echo "一共猜了$total次,次数有点多,加油啊。"
                    elif [ $total -gt 6 ];then
                       echo "一共猜了$total次,行不行,猜了这多次"
                    fi
                    exit 0
             elif [ $PRICE -gt $NUM ]
              then
                    echo "嘿嘿,要不你用这个价买?"
                    echo "再给你一次机会,请继续猜:"
                    apple
             elif [ $PRICE -lt $NUM ]
              then
                    echo "太低太低"
                    echo "再给你一次机会,请继续猜:"
                    apple
             fi
    }
    main(){
    apple
    while true
    do
      guess
    done
    }
    main
    
    
    

      8、手机充值

        手机充值10元,每发一次短信(输出当前余额)花费1角5分钱,当余额地域1角5分钱时就不能再发短信了,提示余额不足,请重置,充值后可以继续发短信

    [root@oldboy C11]# cat 10_5_1.sh
    #!/bin/sh
    export LANG="zh_CN.UTF-8"
    sum=15
    msg_fee=15
    msg_count=0
    menu(){
        cat <<END
    当前余额为${sum}分,每条短信需要${msg_fee}分
    ==========================
          1.充值
          2.发消息
          3.退出
    ==========================
    END
    }
    recharge(){
        read -p "请输入金额充值:" money
            expr $money + 1 &>/dev/null 
            if [ $? -ne 0 ]
               then
                   echo "then money your input is error,must be int."
               else 
                   sum=$(($sum+$money))
                   echo "当前余额为:$sum"
            fi
    }
    sendInfo(){
        if [ ${sum} -lt $msg_fee ]
           then
                printf "余额不足:$sum ,请充值。
    "
           else 
                while true 
                  do
                     read -p "请输入短信内容(不能有空格):" msg
                     sum=$(($sum-$msg_fee))
                     printf "Send "$msg" successfully!
    "
                     printf "当前余额为: $sum
    "
                     if [ $sum -lt 15 ]
                        then
                            printf "余额不足,剩余$sum分
    "
                            return 
                     fi
                done
        fi
    }
    main(){
    while true
    do
       menu
       read -p "请输入数字选择:" num
       case "$num" in
           1)
             recharge
             ;;
           2)
             sendInfo
             ;;
           3)
             exit 
             ;;
           *)
            printf "选择错误,必须是{1|2|3}
    "
       esac
    done
    }
    main

      9、使用while守护进程的方式监控网站,每隔10s确定一次网站是否正常

    #!/bin/sh
    if [ $# -ne 1 ];then
       echo $"usage $0 url"
       exit 1
    fi
    while true
    do
       if [ `curl -o /dev/null --connect-timeout 5 -s -w "%{http_code}"  $1|egrep -w "200|301|302"|wc -l` -ne 1 ]
         then
          echo "$1 is error."
          #echo "$1 is error."|mail -s "$1 is error." 31333741--@qq.com
       else
          echo "$1 is ok"
       fi
       sleep 10
    done
    [root@web1 while-until]# ./4-9.sh 
    usage ./4-9.sh url
    [root@web1 while-until]# ./4-9.sh www.baidu.com 
    www.baidu.com is ok
    ^C
    [root@web1 while-until]# ./4-9.sh www.baidu1111.com 
    www.baidu1111.com is ok
    ^C
    [root@web1 while-until]# ./4-9.sh www.111baidu1111.com 
    www.111baidu1111.com is error.
    ^C
    [root@web1 while-until]# 

    参考学习引用:https://blog.51cto.com/oldboy/1855442

    参考学习图书:<跟老男孩学linux运维:shell编程实战 >

    转载请注明出处:https://www.cnblogs.com/zhangxingeng/p/11412371.html 

  • 相关阅读:
    HDU 5977 Garden of Eden(点分治求点对路径颜色数为K)
    HDU 5828 Rikka with Sequence(线段树区间加开根求和)
    TZOJ 1689 Building A New Barn(求平面上有几个其它点求到n个点的曼哈顿距离最小)
    HDU 5734 Acperience(数学推导)
    POJ 1741 Tree(点分治点对<=k)
    HDU 5723 Abandoned country(kruskal+dp树上任意两点距离和)
    HDU 5988 Coding Contest(最小费用最大流变形)
    TZOJ 1693 Silver Cow Party(最短路+思维)
    TZOJ 4602 高桥和低桥(二分或树状数组+二分)
    TZOJ 2099 Sightseeing tour(网络流判混合图欧拉回路)
  • 原文地址:https://www.cnblogs.com/zhangxingeng/p/11412371.html
Copyright © 2011-2022 走看看