for 循环

  • 当变量值在列表里,for循环即执行一次所有命令,使用变量名获取列表中的当前取值。命令可为任何有效的shell命令和语句。

  • 语法:for 变量名 in 条件; do...;done

  • 案例1

    #!/bin/bash
    sum=0 // 给变量sum赋值
    for i in seq 1 100 // 给i赋值,从1到100
    do
    sum=$[ $sum + $i ]
    // 累加
    done
    echo $sum
    // 输出结果为1到100的和

  • 案例2

    #!/bin/bash
    cd /etc/ // 切换到/etc/目录下
    for a in ls /etc/
    do
    if [ -d $a ] // 判断是否为目录文件
    then
    echo $a
    ls $a
    fi
    done
    // 文件列表循环

  • for默认情况下把空格或者换行符(回车)作为分隔符

    [root@localhost test]# ls
    1 2 3 4.txt
    // 3 4.txt是一个文件(34之间有空格)
    [root@localhost test]# for i in ls ./; do echo $i ; done
    1
    2
    3
    4.txt

while 循环

  • while 循环用于不断的执行一系列的命令,也用于从文件中读取数据,命令通常为测试条件。

  • 语法:while条件;do...;done

  • 案例1 (监控脚本)

    当系统负载大于10的时候,发送邮件,每隔30秒执行一次

    #!/bin/bash
    while :
    do
    load=w | head -1 | awk -F 'load average: ' '{print $2}' | cut -d. -f1
    // w 命令查看负载
    // head -1 只查看第一行
    // awk -F 'load average: '指定分隔符
    // {print $2} 打印第二段
    // cut -d. -f1 以点为分隔符,截取第一段
    if [ $load -gt 10 ]
    // 当$load 大于10 时执行下面命令
    then
    /usr/local/sbin/mail.py xxx@qq.com "load high" "$load"
    // 监控邮箱脚本所在路径
    // 接收邮件的用户、主题、内容
    fi
    sleep 30
    // 每30秒查一次
    done
    // while 后的“:”表示死循环,也可以将:换成true

    执行结果:
    [root@localhost shell]# sh -x while.sh

    • :
      ++ w
      ++ head -1
      ++ awk -F 'load average: ' '{print $2}'
      ++ cut -d. -f1
    • load=0
    • '[' 0 -gt 10 ']'
    • sleep 30

    // 如果不手动停止该脚本,它会一直循环执行(按ctrl+c结束),实际环境中配合screen(虚拟终端)中使用。

  • 案例2

    交互模式下,用户输入一个字符,检测该字符是否符合条件,如:空、非数字、数字。分别对字符做出判断,然后做出不同的回应。

    #!/bin/bash
    while :
    do
    read -p "please input a number:" n
    if [ -z "$n" ]
    // 如果$n为空,则执行then
    then
    echo "你需要输入东西"
    continue
    // 执行到这里时,返回脚本开头重新开始执行
    fi
    n1=echo $n | sed 's/[0-9]//g'
    if [ ! -z "$n1" ]
    // 如果$n不为空,则执行then
    then
    echo "你只能输入一个纯数字"
    continue
    // 执行到这里时,返回到脚本开头重新执行
    fi
    break
    // 如果上面两个条件都没满足,则跳出循环
    done
    echo $n

    执行结果:
    [root@localhost shell]# sh while2.sh
    please input a number:
    你需要输入东西
    please input a number:a
    你只能输入一个纯数字
    please input a number:1
    1

break 跳出循环

  • break 命令允许跳出所有循环(终止执行后面所有循环)。

    #!/bin/bash
    for i in seq 1 5
    do
    echo $i // 输出$i的值
    if [ $i -eq 3 ]
    then
    break
    // 当$i等于3时跳出循环
    fi
    echo $i
    // 没跳出循环就在输出一次$i
    done
    echo "break!"
    // 跳出循环后输出break!

    执行结果:
    [root@localhost shell]# sh break.sh
    1
    1
    2
    2
    3
    break!

continue 结束本次循环

  • continue 命令与break相似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。(忽略掉continue之下的代码,返回脚本开头继续执行)

    #!/bin/bash
    for i in seq 1 5
    do
    echo $i
    if [ $i -eq 3 ]
    then
    continue // 跳出循环
    fi
    echo $i
    done
    echo "break!"

    执行结果:
    [root@localhost shell]# sh continue.sh
    1
    1
    2
    2
    3
    4
    4
    5
    5
    break!
    // 执行到3时,脚本没有结束,又继续执行,所以只有一个3

exit 退出脚本

  • 执行到exit时,直接退出脚本。比break还严谨,break只是跳出循环,但还能执行循环外的命令,但exit不行

    #!/bin/bash
    for i in seq 1 5
    do
    echo $i
    if [ $i -eq 3 ]
    then
    exit // 退出脚本
    fi
    echo $i
    done
    echo "break!"

    执行结果:
    [root@localhost shell]# sh exit.sh
    1
    1
    2
    2
    3
    // 执行到3直接退出,最后循环外的break都没有

select用法

  • select 也是循环的一种,它比较适合用在用户选择的情况下。比如,我们有一个这样的需求,运行脚本后,让用户去选择数字,选择1运行w命令,选择2运行top命令,选择3运行free命令,选择4退出。

    #!/bin/bash
    echo "Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit"
    echo
    select command in w top free quit
    do
    case $command in
    w)
    w
    ;;
    top)
    top
    ;;
    free)
    free
    ;;
    quit)
    exit
    ;;
    *)
    echo "Please input a number:(1-4)."
    ;;
    esac
    done

    执行结果:
    sh select.sh
    Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit

    1) w
    2) top
    3) free
    4) quit
    #? 1
    16:06:58 up 109 days, 22:01, 1 user, load average: 0.11, 0.05, 0.01
    USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
    root pts/0 222.128.156.84 16:05 0.00s 0.00s 0.00s w

    #? 3
    total used free shared buffers cached
    Mem: 1020328 943736 76592 0 86840 263624
    -/+ buffers/cache: 593272 427056
    Swap: 2097144 44196 2052948
    #?

  • 我们发现,select会默认把序号对应的命令列出来,每次输入一个数字,则会执行相应的命令,命令执行完后并不会退出脚本。它还会继续让我们再次输如序号。序号前面的提示符,我们也是可以修改的,利用变量PS3即可,再次修改脚本如下:

    #!/bin/bash
    PS3="Please select a number: "
    echo "Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit"
    echo

    select command in w top free quit
    do
    case $command in
    w)
    w
    ;;
    top)
    top
    ;;
    free)
    free
    ;;
    quit)
    exit
    ;;
    *)
    echo "Please input a number:(1-4)."
    esac
    done

  • 如果想要脚本每次输入一个序号后就自动退出,则需要再次更改脚本如下:

    #!/bin/bash
    PS3="Please select a number: "
    echo "Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit"
    echo

    select command in w top free quit
    do
    case $command in
    w)
    w;exit
    ;;
    top)
    top;exit
    ;;
    free)
    free;exit
    ;;
    quit)
    exit
    ;;
    *)
    echo "Please input a number:(1-4).";exit
    esac
    done