Linux shell - if
最基本的结构化命令是 if-then 语句。
if command
then
commands
fi
也可以把分号(;)放在待求值的命令尾部,可以将 then 语句写在同一行,这样看起来更像其他编程语言中的 if-then 语句。
if command; then
commands
fi
如果之前用过其他编程语言的 if-then 语句,那么这种形式可能会让你有点儿困惑。在其他编程语言中,if 语句之后的对象是一个等式,其求值结果为 TRUE 或 FALSE。但 bash shell 的 if 语句并非如此。
bash shell 的 if 语句会运行 if 之后的命令。如果该命令的退出状态码为 0(命令成功运行),那么位于 then 部分的命令就会被执行。如果该命令的退出状态码是其他值,则 then 部分的命令不会被执行,bash shell 会接着处理脚本中的下一条命令。fi 语句用来表示 if-then 语句到此结束。
用一个简单的例子来解释一下这个概念:
if pwd
then
echo "it worked"
fi
# it worked
shell 执行了 if 行中的 pwd 命令。由于退出状态码是 0,因此它也执行了 then 部分的 echo 语句。
再来看另一个例子:
if IamNotaCommand
then
echo "It worked"
fi
echo "We are outside the if statement"
# We are outside the if statement
在这个例子中,我们在 if 语句中故意使用了一个不存在的命令 IamNotaCommand。由于这是个错误的命令,因此会产生一个非 0 的退出状态码,bash shell 因此跳过了 then 部分的 echo 命令。还要注意,if 语句中的那个错误命令所产生的错误消息依然会显示在脚本的输出中。
在 if-then 语句中,不管命令是否成功执行,你都只有一种选择。如果命令返回一个非 0 退出状态码,则 bash shell 会继续执行脚本中的下一条命令。在这种情况下,如果能够执行另一组命令就好了。这正是 if-then-else 语句的作用。
if-then-else 语句在语句中提供了另外一组命令:
if command
then
commands
else
commands
fi
你可以使用 else 部分的另一种名为 elif 的形式,这样就不用再写多个 if-then 语句了。elif 使用另一个 if-then 语句延续 else 部分:
if command1
then
commands
elif command2
then
more commands
fi
if-then 的高级特性
bash shell 还提供了 3 个可在 if-then 语句中使用的高级特性。
- 在子 shell 中执行命令的单括号。
- 用于数学表达式的双括号。
- 用于高级字符串处理功能的双方括号。
使用单括号
单括号允许在 if 语句中使用子 shell(子 shell 的用法参见第 5 章)。单括号形式的 test 命令格式如下:
(command)
在 bash shell 执行 command 之前,会先创建一个子 shell,然后在其中执行命令。如果命令成功结束,则退出状态码会被设为 0,then 部分的命令就会被执行。如果命令的退出状态码不为 0,则不执行 then 部分的命令。来看一个使用子 shell 进行测试的例子:
echo $BASH_SUBSHELL
if (echo $BASH_SUBSHELL)
then
echo "The subshell command operated successfully."
else
echo "The subshell command was NOT successful."
fi
# 0
# 1
# The subshell command operated successfully.
使用双括号
双括号命令允许在比较过程中使用高级数学表达式。test 命令在进行比较的时候只能使用简单的算术操作。双括号命令提供了更多的数学符号,这些符号对有过其他编程语言经验的程序员而言并不陌生。双括号命令的格式如下:
(( expression ))
val1=10
if (( $val1 ** 2 > 90 ))
then
(( val2 = $val1 ** 2 ))
echo "The square of $val1 is $val2,"
echo "which is greater than 90."
fi
# The square of 10 is 100,
# which is greater than 90.
注意,双括号中表达式的大于号不用转义。这是双括号命令又一个优越性的体现。
使用双方括号
双方括号命令提供了针对字符串比较的高级特性。双方括号的格式如下:
[[ expression ]]
expression 可以使用 test 命令中的标准字符串比较。除此之外,它还提供了 test 命令所不具备的另一个特性——模式匹配。
注意,双方括号在 bash shell 中运行良好。不过要小心,不是所有的 shell 都支持双方括号。
在进行模式匹配时,可以定义通配符或正则表达式(参见第 20 章)来匹配字符串:
if [[ $BASH_VERSION == 5.* ]]
then
echo "You are using the Bash Shell version 5 series."
fi
# You are using the Bash Shell version 5 series.