Bash 没有布尔值的概念。 它只有字符串和数字,以及由字符串或数字组成的数组。 那么,条件命令是如何处理 true 和 false 的呢?
命令结束时会产生一个_退出状态_。 退出状态是一个 0 到 255 之间(含两端)的整数。 Bash 认为退出状态为零表示_成功_。 其他任何退出状态都表示_失败_。
这一点适用于所有命令,包括 Bash 的内置命令、关键字和函数。
if命令的基本语法是
if CONDITIONAL_COMMANDS; then TRUE_COMMANDS; else FALSE_COMMANDS; fi
它以if开头,条件命令与“成功”命令之间用then分隔,最后以fi结束。
else子句是可选的。
CONDITIONAL_COMMANDS 可以是一条命令,也可以是一个命令列表。
CONDITIONAL_COMMANDS 会被执行,然后
可以用elif给出级联分支
if CONDITIONAL_COMMANDS
then TRUE_COMMANDS
elif CONDITIONAL_COMMANDS_2
then TRUE_COMMANDS_2
# more elif branches ...
else FALSE_COMMANDS
fi
在then、elif、else和fi这些词之前,必须有分号或换行。
需要强调的是:控制流程的是条件命令的退出状态。
举个例子,grep在找到匹配时返回 0,没找到时返回 1。
-q选项会抑制输出,只产生退出状态。
if grep -q "my pattern" my_file; then echo "the pattern is found in the file"; fi
CONDITIONAL_COMMANDS 周围并没有什么特殊语法。 你可能见过像下面这样的 if 语句:
if [ "$password" = "secure" ]; then
echo "Welcome!"
fi
[并不是特殊语法。
它是一个_命令_,会计算条件表达式,并以成功或失败的状态退出。
和所有命令一样,它与实参之间必须有空白字符。
[其实是test命令的同义词。
两者完全相同,只不过[的最后一个实参_必须_是]。
在[和]之间,你要写一个条件表达式。
一些典型的条件表达式包括:
[ -f "$filename" ] # file operations
[ "$string1" = "$string2" ] # string comparisons
[ "$num1" -eq "$num2" ] # arithmetic comparisons
还有更多可用的运算,它们列在手册的 Bash 条件表达式 一节中。
在上面的例子中,注意所有变量都加了引号。
test和[命令是普通命令,它们的实参和其他命令一样,会发生单词拆分和文件名展开。
这一点值得强调,因为条件表达式会根据你提供的_实参个数_而有不同的求值方式:
[ -z "$name" ]),或者是一个!(对 1 个实参测试的结果取反)如果忘了加引号,可能会得到意想不到的结果:
str=""
# this prints "empty"
if [ -n "$str" ]; then echo "not empty"; else echo "empty"; fi
# leaving the variable unquoted results in incorrect "not empty" output
if [ -n $str ]; then echo "not empty"; else echo "empty"; fi
[[...]]条件结构不是_命令_,而是一个关键字。
这意味着,虽然它的处理方式和其他命令一样,但它有特殊的解析规则。
[[的特殊之处在于,其中展开的变量不会发生单词拆分或文件名展开。
也就是说,即使不加引号,这条命令的行为也符合你的预期。
if [[ -n $str ]]; then echo "not empty"; else echo "empty"; fi
[[支持test和[能处理的所有条件表达式。
此外,[[还提供
=~正则表达式匹配运算符,==和!=作为通配模式匹配运算符使用,&&和||作为逻辑运算符(特殊解析规则),<和>作为“裸”的字符串比较运算符(特殊解析规则:因为它们也是重定向符号,所以在[中必须转义)。人们普遍认为,这些特殊功能带来的好处很大,所以应该只使用[[。
(例如 Google Shell Style Guide。)
case是另一种控制流命令。
它类似于其他语言中的“switch”语句。
case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac
WORD 会依次与每个 PATTERN 匹配。 一旦有模式匹配上,就会执行对应的 COMMANDS。
read -p "Guess the secret word: " word
case "$word" in
secret) echo "Yes, you guessed it!" ;;
??????) echo "That's the right number of letters." ;;
s*) echo "You guessed the first letter." ;;
*) echo "Not even close! Try again." ;;
esac
每个 COMMANDS 子句都必须以两个分号;;结尾。