Shell中的流程控制

需要在sh文件中,判断是否为root运行,整理了一下,就有本文了。

if 条件判断

condition里可以是一个条件,也可以是多少个条件。

一次条件判断

Bash
if condition ; then # then 如果是换行,就不需要[;]
    true-command
else
    false-command
fi
# 写在一行上
if condition ; then true-command ; else false-command ; fi

二次条件判断

Bash
if condition1
then
    condition1-true-command1
elif conditionN ; then 
    conditionN-true-commandN
else
    false-command
fi

condition里有多个条件写法

Bash
# 多条件ADN
if [ condition1 -a condition2 ]
if [ condition1 ] && [ condition2 ]
if [[ condition1 && condition2 ]]
# 多条件 OR
if [ condition1 -o condition2 ]
if [ condition1 ] || [ condition2 ]
if [[ condition1 || condition2 ]]

if [ ] 与 if [[ ]]的区别

特性[ ] (test 命令)[[ ]] (条件表达式)
类型内置命令Shell 关键字
可移植性POSIX 标准,所有 Shell 都支持Bash/Zsh 等扩展,不是 POSIX 标准
单词分割会进行单词分割和路径扩展不会进行单词分割和路径扩展
逻辑运算符-a (AND), -o (OR)&& (AND), || (OR)
模式匹配不支持支持 == 和 =~ 模式匹配
字符串比较需要引号防止空变量问题更安全,空变量不会造成问题
  • [[ ]] 通常比 [ ] 更快,因为它是 Shell 关键字而不是外部命令
  • [[ ]] 不需要为变量加引号,减少了字符串处理开销;使用 [ ] 时,记得给变量加引号。
  • 在 Bash 脚本中优先使用 [[ ]],如果需要跨 Shell 兼容性,使用 [ ]

case 值判断

$KEY可以为变量或常数,匹配到某一值后,执行命令直至;;结束。注意:

  • 一旦匹配到,则执行完相应命令后,不再继续匹配。
  • 如果无一个匹配到,使用星号 * 捕获该值,再执行后面的命令。
Bash
case $KEY in
    值1)
        command-zone-1
        ;;
    值2)
        command-zone-2
        ;;
    值N)
        command-zone-N
        ;;
    *)
        command-zone-N
        ;;
esac

示例1:

Bash
echo '你输入的数字为:'
read aNum # 从键盘读取值,赋给变量
case $aNum in
    1)  echo '你选择了 1'
    ;;
    2)  echo '你选择了 2'
    ;;
    3)  echo '你选择了 3'
    ;;
    4)  echo '你选择了 4'
    ;;
    *)  echo '你没有输入 1 到 4 之间的数字'
    ;;
esac

输出1:

你输入的数字为:
3
你选择了 3

示例2:

Bash
site="runoob"
case "$site" in
   "runoob") echo "菜鸟教程"
   ;;
   "google") echo "Google 搜索"
   ;;
   "taobao") echo "淘宝网"
   ;;
esac
# 输出为:菜鸟教程

for :对所有入参,按先后顺序,循环执行。

Bash
for var in item1 item2 ... itemN
do
    command
done

当变量的值在列表里,for 循环即执行一次所有命令,使用变量名获取列表中的当前取值。

  • 命令可为任何有效的 shell 命令和语句。
  • in 列表可以包含替换、字符串和文件名。in列表是可选的,如果不用它,for循环使用命令行的位置参数。
    示例:
Bash
for loop in 1 2 3
do
    echo "The value is: $loop"
done

输出:

The value is: 1
The value is: 2
The value is: 3

while 与 until 的循环:执行命令,直到条件为 false / true 才停止。

区别:

  • while 循环:执行命令,直到条件为 false 才停止。
  • until 循环:执行命令,直至条件为 true 时停止。
Bash
# while 循环:执行命令,直到条件为 false 才停止。
while condition  # condition为[:]或[true]字符时,代表无限循环,因为不存在条件为false的时候。
do
    command
done

# until 循环:执行命令,直至条件为 true 时停止。
until condition
do
    command
done

示例:如果 int 小于等于 5,那么条件返回真。int 从 1 开始,每次循环处理时,int 加 1。运行上述脚本,返回数字 1 到 5,然后终止。

Bash
int=1
while(( $int<=5 ))
do
    echo $int
    let "int++"
done

输出:

1
2
3
4
5

跳出循环:break 和 continue

在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,break 和 continue 的区别:

  • break 命令允许跳出所有循环(终止执行后面的所有循环)。
  • continue 命令与 break 命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。
breakcontinue

break 示例:

Bash
while :
do
    echo -n "输入 1 到 5 之间的数字:"
    read aNum
    case $aNum in
        1|2|3|4|5) echo "你输入的数字为 $aNum!"
        ;;
        *) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
            break
        ;;
    esac
done

break 示例输出:

输入 1 到 5 之间的数字:3
你输入的数字为 3!
输入 1 到 5 之间的数字:7
你输入的数字不是 1 到 5 之间的! 游戏结束

continue 示例:

Bash
while :
do
    echo -n "输入 1 到 5 之间的数字: "
    read aNum
    case $aNum in
        1|2|3|4|5) echo "你输入的数字为 $aNum!"
        ;;
        *) echo "你输入的数字不是 1 到 5 之间的!"
            continue
            echo "游戏结束"
        ;;
    esac
done

当输入大于5的数字时,该例中的循环不会结束,而语句echo "游戏结束" 永远不会被执行。

中断执行:return [N]、exit [N]

  • exit:退出当前shell进程,返回n值(0~255),未指定为0,代表成功。
  • return:退出当前函数方法(所以,也只能在函数里面使用 return,在函数外执行return语句会返回失败),返回n值(0~255),未指定为0,代表成功。
    test.sh 示例 :
Bash
#!/bin/bash
if [ -n "$SUDO_USER" -o "$USER" != "root" ]; then
    echo -e "\n请切换到root用户,再执行[ sh $0 ]。"
    exit 1 # 使用了sudo或不是root用户运行,则退出脚本;
fi
function abnormalCheck {
    local aC_DIR=$1
    if [ ! -d ${aC_DIR} ]; then return 1; fi
    echo abcdef
    if [ "${aC_DIR}" =  "/data/123" ]; then return 0; fi # update 不需要备份
    echo 123456
}
abnormalCheck /data/abc
abnormalCheck /data/xyz
abnormalCheck /data/123
abnormalCheck /data/456
exit
  1. 如果是非root用户运行sh test.sh,或使用sudo sh test.sh运行,文件中,第5行后的命令,都不会被执行,因为在前面被exit 1退出shell了。
  2. root用户运行,则会执行 abnormalCheck 函数4次。
    • 每次 abnormalCheck 执行时,如果路径不存在,就看不到二行输出:abcdef123456;因为被 return 1退出函数执行,但由于有 4 行 abnormalCheck 命令,所以后还没有执行的,会继续执行。
    • 对于 /data/123 路径,即存在,也只能看到一行输出:abcdef,而123456是看不到的,因为被 return 0 退出函数执行。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注