基本分支结构

if-then(-else) 语法

1
2
3
4
if command
then
commands
fi

1
2
3
4
5
if command; then
commands
else
commands
fi

bash shell 的 if 语句会运行 if 后面的那个命令。如果该命令的退出状态码是 0(该命令成功运行),位于 then 部分的命令就会被执行。如果该命令的退出状态码是其他值部分的命令,就 else 部分的命令会被执行,bash shell 会继续执行脚本中的下一个命令。fi 语句用来表示 if-then 语句到此结束。

当你想要实现多次判断条件来进行多分支时,可以使用 else 部分的另一种形式:elif。这样就不用再书写多个 if-then 语句了。elif 使用另一个 if-then 语句延续 else 部分。

1
2
3
4
5
6
7
8
9
if command1
then
commands
elif command2
then
more commands
else
commands
fi

注意:记住,在 elif 语句中,紧跟其后的 else 语句属于 elif 代码块。它们并不属于之前的 if-then 代码块。

if-then 语句本身不能测试命令退出状态码之外的条件,它需要借助其他命令或语法。下面分别介绍几种常用的方法。

test 命令

test 命令提供了在 if-then 语句中测试不同条件的途径。如果 test 命令中列出的条件成立,test 命令就会退出并返回退出状态码 0。这样 if-then 语句就与其他编程语言中的 if-then 语句以类似的方式工作了。如果条件不成立,test 命令就会退出并返回非零的退出状态码,这使得 if-then 语句不会再被执行。

test 命令格式(condition 是 test 命令要测试的一系列参数和值): test condition

示例:

1
2
3
4
5
6
7
8
9
10
$ str=2

# violetv at manjaro in ~ [20:10:49]
$ if test $str==2
if> then
then> echo "1"
then> else
else> echo 0
else> fi
1

条件测试

bash shell 提供了另一种条件测试方法,无需在 if-then 语句中声明 test 命令。

1
2
3
4
if [ condition ]
then
commands
fi

方括号定义了测试条件。注意,第一个方括号之后和第二个方括号之前必须加上一个空格,否则就会报错。 test 命令可以判断三类条件:

  1. 文件比较

    这一类比较测试很有可能是 shell 编程中最为强大、也是用得最多的比较形式。它允许你测试 Linux 文件系统上文件和目录的状态。

    | 比 较 | 描 述| | -d file | 检查 file 是否存在并是一个目录| | -e file | 检查 file 是否存在| | -f file | 检查 file 是否存在并是一个文件| | -r file | 检查 file 是否存在并可读| | -s file | 检查 file 是否存在并非空| | -w file | 检查 file 是否存在并可写| | -x file | 检查 file 是否存在并可执行| | -O file | 检查 file 是否存在并属当前用户所有| | -G file | 检查 file 是否存在并且默认组与当前用户相同| | file1 -nt file2 | 检查 file1 是否比 file2 新| | file1 -ot file2 | 检查 file1 是否比 file2 旧|

    注意:如果文件不存在,-nt 比较会返回一个错误的结果。在你尝试使用-nt 或 -ot 比较文件之前,必须先确认文件是存在的

  2. 数值比较

    适用于整数和整型变量,不适用于浮点数

    比 较 描 述
    n1 -eq n2 检查 n1 是否与 n2 相等
    n1 -ge n2 检查 n1 是否大于或等于 n2
    n1 -gt n2 检查 n1 是否大于 n2
    n1 -le n2 检查 n1 是否小于或等于 n2
    n1 -lt n2 检查 n1 是否小于 n2
    n1 -ne n2 检查 n1 是否不等于 n2
  3. 字符串比较

    比 较 描 述
    str1 = str2 检查 str1 是否和 str2 相同
    str1 != str2 检查 str1 是否和 str2 不同
    str1 < str2 检查 str1 是否比 str2 小
    str1 > str2 检查 str1 是否比 str2 大
    -n str1 检查 str1 的长度是否非 0
    -z str1 检查 str1 的长度是否为 0

    注意:

    1. 在比较字符串的相等性时,比较测试会将所有的标点和大小写情况都考虑在内

    2. 空的和未初始化的变量会对 shell 脚本测试造成灾难性的影响。如果不是很确定一个变量的内容,最好在将其用于数值或字符串比较之前先通过-n 或-z 来测试一下变量是否含有值。

    3. test 命令和测试表达式使用标准的数学比较符号来表示字符串比较,而用文本代码来表示数值比较。这个细微的特性被很多程序员理解反了。如果你对数值使用了数学运算符号,shell 会将它们当成字符串值,可能无法得到正确的结果。

    4. 字符串大小比较

      1. 大于号和小于号必须转义,否则 shell 会把它们当作重定向符号,把字符串值当作文件名;

      2. 大于和小于顺序和 sort 命令所采用的不同。

        除非你经常处理大小写字母,否则几乎遇不到。sort 命令处理大写字母的方法刚好跟 test 命令相反。 在比较测试中,大写字母被认为是小于小写字母的。但 sort 命令恰好相反。当你将同样的字符串放进文件中并用 sort 命令排序时,小写字母会先出现。这是由各个命令使用的排序技术不同造成的。

复合条件测试

if-then 语句允许你使用布尔逻辑来组合测试。有两种布尔运算符可用: [ condition1 ] && [ condition2 ] [ condition1 ] || [ condition2 ]

布尔逻辑是一种能够将可能的返回值简化为 TRUE 或 FALSE 的方法。

if-then 高级特性

bash shell 提供了两项可在 if-then 语句中使用的高级特性:

  • 用于数学表达式的双括号
  • 用于高级字符串处理功能的双方括号

算数扩展

算数扩展(双括号)允许你在比较过程中使用高级数学表达式。test 命令只能在比较中使用简单的算术操作。具体可以进行的操作我已经在 - [ ] shell 数学运算 写到

双方括号

双方括号命令提供了针对字符串比较的高级特性。双方括号命令的格式如下:[[ expression ]]

双方括号里的 expression 使用了 test 命令中采用的标准字符串比较。但它提供了 test 命令未提供的另一个特性——模式匹配(pattern matching)。

说明:双方括号在 bash shell 中工作良好。不过要小心,不是所有的 shell 都支持双方括号。

条件测试总结

正常操作直接用算数扩展 (()), 字符串简单模式匹配使用双方括号 [[]]

case 分支

case 命令会采用列表格式来检查单个变量的多个值。

1
2
3
4
5
6
7
8
case variable in
pattern1 | pattern2)
commands1;;
pattern3)
commands2;;
*)
commands;;
esac

命令会将指定的变量与不同模式进行比较。如果变量和模式是匹配的,那么 shell 会执行为该模式指定的命令。可以通过竖线操作符在一行中分隔出多个模式模式。星号会捕获所有与已知模式不匹配的值。

参考资料

  1. Linux 命令行与 Shell 脚本编程大全