• shell使用循环


     1. for循环

      脚本在执行任务的时候,总会遇到需要循环执行的时候,比如说我们需要脚本每隔五分钟执行一次ping的操作,除了计划任务,我们还可以使用脚本来完成,那么我们就用到了循环语句。

     1.1 for循环语法1 -- for .. in ..

            for var in value1 value2 ...
        do
          要执行的代码块
       done

    #!/bin/bash
    
    #1 for直接赋值
    #for var in 1 2 3 4 5
    
    #2 使用命令赋值
    #for var in `seq 1 2 9`
    
    #3 使用字符串赋值(这个字符串可以是使用命令后的结果)
    for var in hello linux, hello c,java and more
      do
        echo $var
        sleep 0.5
    done
    
    #上面第3个的执行结果如下:
      [root@haha shell_0411]# sh for_1.sh 
      hello
      linux,
      hello
      c,java
      and
      more

      也可以 for ..;do 连起来使用

    #!/bin/bash
    
    for var in 1 2 3 4 5;do    
        echo $var
        sleep 0.5
    done

     1.2 for循环语法2 -- C式

      for ((变量;条件;自增减运算 ))
        do

          要执行的代码块
      done

    #!/bin/bash
    
    #for循环使用单个变量
    for ((i=1;i<10;i++))
      do
        echo $i
    done
    
    
    echo "for sysle with more var"
    
    #for循环使用多个变量
    for ((a=1,b=9;a<10,b>0;a++,b--))
      do
        echo $a -- $b
    done

      得出来的结果如下:

    [root@haha shell_0411]# sh for_c_style.sh 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    for sysle with more var
    1 -- 9
    2 -- 8
    3 -- 7
    4 -- 6
    5 -- 5
    6 -- 4
    7 -- 3
    8 -- 2
    9 -- 1

      1.3 for死循环

      for ((;;))
      do
        要执行的代码块
      done

      1.4 for循环break和continue

      continue:跳过循环中的某次循环,继续执行下次循环

      break:跳出当前循环,继续执行循环体之外的代码

        break N:break后面跟数字,可以一次性跳出N层循环。嵌套循环从内到外依次是第1层、第2层、第3层....例如 break 2,就表示跳出内外两层循环(当前循环以及外面一层循环)。 

      continue和break的基本用法如下:

    #!/bin/bash
    # 用户输入什么就输出什么,如果输入为0就跳过,输入为q就退出
    
    for ((;;))
      do
        read -p "char: " ch
        if [ $ch -eq 0 ]
          then
            continue
        elif [ $ch == "q" ]
          then
            break
        else
          echo "当前输入为:$ch"
        fi
    done

      break N 的用法:脚本中的 break 2,就表示跳出本层以及本层之外的那层循环,总共两层循环, 如:

    #!/bin/bash
    #如果用户输入0就跳出当前循环,如果输入q程序直接退出
    
    for ((;;))
      do
        echo "外循环开始>>>"
        for ((;;))
          do
            read -p "内循环请输入:" ch
            if [ $ch == "q" ]
              then
                break 2
            elif [ $ch == 0 ]
              then
                break
            else
              echo "您输入的为:$ch"
            fi
        done
    done

      for循环练习:

      例1: 写一个监控某个主机是否存活的脚本

      脚本中的命令说明:

        1、ping -c1 -w1 中 -c1是指ping的次数,-w是指执行的超时时间,单位为秒
        2、&>/dev/null 是指标准输出和错误输出都输出到/dev/null上,而不在界面上显示

    #!/bin/bash
    #监控某个主机存活的脚本
    
    for ((;;))
      do
        ping -c1 $1 &>/dev/null
        if (($? == 0))
          then
            echo -e "$1的主机还存活着,当前时间为: `date "+%F %H:%M:%S"`"
          else
            echo -e "$1的主机已经失去联系,当前时间为: `date "+%F %H:%M:%S"`"
        fi
        sleep 5
    done
    
     执行脚本: bash monitor_service.sh 192.168.17.137
    
      输出结果如下:
    
     [root@haha shell_0413]# bash monitor_service.sh 192.168.17.137
     192.168.17.137的主机还存活着,当前时间为: 2020-04-16 00:00:04
     192.168.17.137的主机还存活着,当前时间为: 2020-04-16 00:00:09

       例2: 输入一个ip文件,检查该文件中有哪些能用的ip,并记录下来

       串行版: 

          注意: >ip.log 先清日志内容

    #!/bin/bash
    #输入一个ip文件,检查该文件中有哪些能用的ip,并记录下来
    
    >ip.log
    for ip in `cat $1`
      do
        ping_flag="down"
        ping -c1 -w3 $ip &>/dev/null
        if [ $? -eq 0 ]; then
            ping_flag="up"
        fi
        echo "the $ip is $ping_flag!" | tee -a ip.log
    done

       并行版:

        注意:{}& 是采用并行的方式并放在后台执行;

              wait 是等待后台所有ip都检查完再往下走。

    #!/bin/bash
    #输入一个ip文件,检查该文件中有哪些能用的ip,并记录下来
    
    >ip.log
    for ip in `cat $1`
      do
         {
          ping_flag="down"
          ping -c1 -w3 $ip &>/dev/null
          if [ $? -eq 0 ]; then
            ping_flag="up"
          fi
          echo "the $ip is $ping_flag!" | tee -a ip.log
         }&
    done
    wait
    echo "finish..."

       例3: 按照用户文件来添加用户和密码

        注意:1. IFS=$':' 或  $'-'  或  $'/'  或...  来重新定义分隔符;

           2. 为什么要重新定义分隔符?

             for line in `cat  adduser.txt`  ==> 转为for循环时为  for line in user1  123123  user2  123456  user3  123321,默认的分隔符为 空格, 不重新定义分隔符的话就按照空格分开,则 $password 为空。

    #!/bin/bash
    #添加adduser.txt中的用户和密码
    
    # 判断是否有参数传进来
    if [ $# == 0 ]; then
        echo "error info: `basename $0 need a detail argument!`"
        exit 1
    fi
    
    # 判断传进来的参数是不是一个具体文件
    if [ ! -f $1 ]; then
        echo "error info: it mast be a file, not directory!"
        exit 2
    fi
    
    # 希望for处理文件时按照回车符分割,而不是空格或tab空格,可以用 IFS 重新定义分隔符
    # 以换行为分隔符,这块必须是单引号,不然会被转义
    IFS=$'
    '
    
    for line in `cat $1`
    do
        if [ ${#line} == 0 ]; then
            echo "Nothing to do"
            continue
        fi
        user=`echo $line | awk '{print $1}'`
        password=`echo $line | awk '{print $2}'`
        id $user &>/dev/null
        if [ $? == 0 ]; then
            echo "user $user already exists!"
        else
            useradd $user
            echo $password | passwd --stdin $user &>/dev/null
            if [ $? == 0 ]; then
                echo "$user is created"
            fi
      fi
    done

      对于处理文件的操作时,while 比 for 循环好用,不用考虑分隔符,while 是逐行读文件,对行数据进行操作。

    2. while循环

     2.1 while 语法

        while [ condition ]     #注意,条件为真while才会循环,条件为假,while停止循环
        do
          commands
        done

     2.2 while 或 for 取舍?

      知道循环次数就可以用for,比如说一天需要循环24次;如果不知道代码要循环多少次,那就用while。

     2.3 用while处理文件更方便

      用for循环处理文件,在遍历时会因为空格的存在,要重新指定分隔符;但是while处理文件时,逐行读取文件内容。如上 for 循环的最后一个例子。

      使用 while 循环对for循环的例3重新编写:

    #!/bin/bash
    #使用while对adduser.txt内容处理,添加用户
    
    while read line
    do
        if [ ${#line} == 0 ]; then
            echo "Nothing to do!"
            continue
        fi
        user=`echo $line | awk '{print $1}'`
        password=`echo $line | awk '{print $2}'`
        id $user &>/dev/null
        if [ $? == 0 ]; then
            echo "user $user is already exists!"
        else
            useradd $user
            echo $password | passwd --stdin $user &>/dev/null
            if [ $? == 0 ]; then
                echo "$user has been created"
            fi
        fi
    done < adduser.txt

     2.4 while死循环 -- while :  或  while true

        注意:let start++ 或 start=$((start+1))  都可以实现累加。

    #!/bin/bash
    
    start=1
    while [ $start -le 10 ]
    do
        if [ $start == 5 ]; then
    #        let start++
            start=$((start+1))
            continue
        else
            echo "start = $start"
        fi
    #    let start++
        start=$((start+1))
    done

     3. shell内置命令 -- shift

     shift:将所有的位置参数向左移n位,默认是shift 1,即位置参数向左移一位;shift 2时,位置参数个数必须是2的整数倍。

    #!/bin/bash
    # 用shift实现位置参数左移
    
    while [ $# -ne 0 ];do
        let sum+=$1
        shift 
    done
    
    echo "sum is : $sum"

     调用脚本时, sh filename.sh 1 2 3 4 5,第一个位置参数$1为1,每执行一次while循环,遇到while,就会将参数1 2 3 4 5向左移一位,变成2 3 4 5,第一个位置参数$1变成2,以此类推,直至$1没有值,循环结束。

  • 相关阅读:
    SpringMVC之数据处理及跳转
    SpringMVC之控制器Controller和RestFul风格
    第一个SpringMVC程序
    什么是SpringMVC
    Spring声明式事务
    【嘎】字符串-反转字符串
    【嘎】字符串-字符串中的单词数
    【嘎】二叉树-226. 翻转二叉树
    【嘎】数组-面试题 01.07. 旋转矩阵-看题解
    【嘎】字符串-统计位数为偶数的数字
  • 原文地址:https://www.cnblogs.com/bk9527/p/12829847.html
Copyright © 2020-2023  润新知