Shell流程控制:while/until 循环

版权声明:可以随意转载→_→ https://blog.csdn.net/ds19991999/article/details/82813480

流程控制:while/until 循环

while

#!/bin/bash
# while-count: display a series of numbers
count=1
while [ $count -le 5 ]; do
    echo $count
    count=$((count + 1))
done
echo "Finished."

优化上一节的菜单脚本:

#!/bin/bash
# while-menu: a menu driven system information program
DELAY=3 # Number of seconds to display results
while true; do
    clear
    cat <<- _EOF_
        Please Select:
        1. Display System Information
        2. Display Disk Space
        3. Display Home Space Utilization
        0. Quit
    _EOF_
    read -p "Enter selection [0-3] > "
    if [[ $REPLY =~ ^[0-3]$ ]]; then
        if [[ $REPLY == 1 ]]; then
            echo "Hostname: $HOSTNAME"
            uptime
            sleep $DELAY
            continue
        fi
        if [[ $REPLY == 2 ]]; then
            df -h
            sleep $DELAY
            continue
        fi
        if [[ $REPLY == 3 ]]; then
            if [[ $(id -u) -eq 0 ]]; then
                echo "Home Space Utilization (All Users)"
                du -sh /home/*
            else
                echo "Home Space Utilization ($USER)"
                du -sh $HOME
            fi
            sleep $DELAY
            continue
        fi
        if [[ $REPLY == 0 ]]; then
            break
        fi
    else
        echo "Invalid entry."
        sleep $DELAY
    fi
done
echo "Program terminated."

shell中的循环支持break和continue

until

#!/bin/bash
# until-count: display a series of numbers
count=1
until [ $count -gt 5 ]; do
    echo $count
    count=$((count + 1))
done
echo "Finished."

疑难排解

  • 丢失引号

  • 丢失意外的标记

  • 预料不到的展开

  • 逻辑错误

    • 不正确的条件表达式。很容易编写一个错误的 if/then/else 语句,并且执行错误的逻辑。 有时候逻辑会被颠倒,或者是逻辑结构不完整。
    • “超出一个值”错误。当编写带有计数器的循环语句的时候,为了计数在恰当的点结束,循环语句 可能要求从 0 开始计数,而不是从 1 开始,这有可能会被忽视。这些类型的错误要不导致循环计数太多,而“超出范围”, 要不就是过早的结束了一次迭代,从而错过了最后一次迭代循环。
    • 意外情况。大多数逻辑错误来自于程序碰到了程序员没有预见到的数据或者情况。这也 可以包括出乎意料的展开,比如说一个包含嵌入式空格的文件名展开成多个命令参数而不是单个的文件名。
  • 防错编程:计算脚本所使用的程序和命令的退出状态。看看下面脚本运行错误的后果。

#!/bin/bash
cd $dir_name
rm *

可以这样改进:cd $dir_name && rm *,但是有可能未设置变量 dir_name 或其变量值为空,导致删除了用户家目录下面的所有文件。&& cd $dir_name && rm *

if [[ -d $dir_name ]]; then
    if cd $dir_name; then
        rm *
    else
        echo "cannot cd to '$dir_name'" >&2
        exit 1
    fi
else
    echo "no such directory: '$dir_name'" >&2
    exit 1
fi
  • 验证输入:如果一个程序可以接受输入数据,那么这个程序必须能够应对它所接受的任意数据。

测试

早发布,常发布:如果在开发周期的早期发现 bug,那么这些 bug 就越容易定位,而且越能低成本 的修复。比喻上述删除文件的操作非常危险,所以我们可以先这样进行测试,打印出要执行的语句就行:

if [[ -d $dir_name ]]; then
    if cd $dir_name; then
        echo rm * # TESTING
    else
        echo "cannot cd to '$dir_name'" >&2
        exit 1
    fi
else
    echo "no such directory: '$dir_name'" >&2
    exit 1
fi
exit # TESTING

测试案例

通过谨慎地选择输入数据或者运行边缘案例和极端案例来完成测试。比喻上述脚本,我们要测试:

  1. dir_name 包含一个已经存在的目录的名字
  2. dir_name 包含一个不存在的目录的名字
  3. dir_name 为空

调试

一个设计良好的脚本会对查找错误有帮助。设计良好的脚本应该具备防卫能力, 能够监测异常条件,并能为用户提供有用的反馈信息。

找到问题区域

隔离脚本中与出现的问题相关的代码区域对查找问题很有帮助。 隔离的代码区域并不总是真正的错误所在,但是隔离往往可以深入了解实际的错误原因。

追踪

添加提示信息追踪代码片段。把提示信息输出到标准错误输出,让其从标准输出中分离出来。bash 还提供了一种名为追踪的方法,这种方法可通过 -x 选项和 set 命令加上 -x 选项两种途径实现。

#!/bin/bash -x
# trouble: script to demonstrate common errors
number=1
if [ $number = 1 ]; then
    echo "Number is equal to 1."
else
    echo "Number is not equal to 1."
fi

or

#!/bin/bash
# trouble: script to demonstrate common errors
number=1
echo "number=$number" # DEBUG
# 为脚本中的一块选择区域,而不是整个脚本启用追踪
set -x # Turn on tracing
if [ $number = 1 ]; then
    echo "Number is equal to 1."
else
    echo "Number is not equal to 1."
fi
set +x # Turn off tracing

行首的加号表明追踪的迹象,使其与常规输出结果区分开来。使用单引号是为了防止变量展开。

  • 执行时检查数值:伴随着追踪,在脚本执行的时候显示变量的内容,以此知道脚本内部的工作状态,往往是很用的。 使用额外的 echo 语句通常会奏效。

猜你喜欢

转载自blog.csdn.net/ds19991999/article/details/82813480