条件测试结构
1.if/then 结构
if/then
结构用来判断命令列表的退出状态码是否为 0,因为0表示成功,如果成功的话,这里应该那么就执行接下来的一个或多个命令。
注意: 这里与 C 语言的等其它语言不同,不能直接使用 0 或者 1 作为判断条件,而应该以 false
,true
代替。以其它大多数语言相反的 true 返回的是0,false 返回的是1
有一个专有命令 [
(左中括号,特殊字符)。这个命令与 test
命令等价,由于效率上的考虑,bash 将它作为一个内建命令。
注意: 由于 bash
的语法检查机制,如果在条件测试时只使用一个 [
将会出现一个错误提示,为了避免这个问题,我们通常将使用一对方括号包含条件测试[]
在版本2.02的 Bash 中, 引入了 "[[ ... ]]"
扩展测试命令,[[
是一个关键字,并不是一个命令。
if 命令能够测试任何命令,并不仅仅是中括号中的条件。
$ vim test.sh
输入代码:
#!/bin/bash
# 逐字节比较a b两个文件是否相同
if cmp a b &> /dev/null # 禁止输出.
then echo "Files a and b are identical."
else echo "Files a and b differ."
fi
程序截图:
运行:
# 非常有用的"if-grep"结构:
# ------------------------
if grep -q Bash file
then echo "File contains at least one occurrence of Bash."
fi
程序截图:
运行:
word=Linux
letter_sequence=inu
if echo "$word" | grep -q "$letter_sequence"
# "-q" 选项是用来禁止输出的.
then
echo "$letter_sequence found in $word"
else
echo "$letter_sequence not found in $word"
fi
程序截图:
运行:
2.多级比较(应注意与嵌套条件分支区分)
$ vim test.sh
输入代码:
#!/bin/bash
# 这里应该理解为子if/then当做一个整体作为测试条件
if echo "Next *if* is part of the comparison for the first *if*."
if [[ $comparison = "integer" ]]
then (( a < b )) # (( 算数表达式 )), 用作算数运算
else
[[ $a < $b ]]
fi
then
echo '$a is less than $b'
fi
程序截图:
注意: ((...))
和 let...
如果运算结果为非0,该语句退出码为0,否则为1; [[...]]
是作为一个单独的语句并且会返回一个退出码
运行代码:
$ bash test.sh
3.真假判断
$ vim test.sh
输入代码:
#!/bin/bash
# 小技巧:
# 如果你不能够确定一个特定的条件该如何进行判断,
#+ 那么就使用if-test结构.
echo
echo "Testing \"0\""
if [ 0 ] # zero
then
echo "0 is true."
else
echo "0 is false."
fi # 0 为真.
echo
echo "Testing \"1\""
if [ 1 ] # one
then
echo "1 is true."
else
echo "1 is false."
fi # 1 为真.
echo
echo "Testing \"-1\""
if [ -1 ] # 负1
then
echo "-1 is true."
else
echo "-1 is false."
fi # -1 为真.
echo
echo "Testing \"NULL\""
if [ ] # NULL (空状态)
then
echo "NULL is true."
else
echo "NULL is false."
fi # NULL 为假.
echo
echo "Testing \"xyz\""
if [ xyz ] # 字符串
then
echo "Random string is true."
else
echo "Random string is false."
fi # 随便的一串字符为真.
echo
echo "Testing \"\$xyz\""
if [ $xyz ] # 判断$xyz是否为null, 但是...
# 这只是一个未初始化的变量.
then
echo "Uninitialized variable is true."
else
echo "Uninitialized variable is false."
fi # 未定义的初始化为假.
echo
echo "Testing \"-n \$xyz\""
if [ -n "$xyz" ] # 更加正规的条件检查.
then
echo "Uninitialized variable is true."
else
echo "Uninitialized variable is false."
fi # 未初始化的变量为假.
echo
xyz= # 初始化了, 但是赋null值.
echo "Testing \"-n \$xyz\""
if [ -n "$xyz" ]
then
echo "Null variable is true."
else
echo "Null variable is false."
fi # null变量为假.
echo
# 什么时候"false"为真?
echo "Testing \"false\""
if [ "false" ] # 看起来"false"只不过是一个字符串而已.
then
echo "\"false\" is true." #+ 并且条件判断的结果为真.
else
echo "\"false\" is false."
fi # "false" 为真.
echo
echo "Testing \"\$false\"" # 再来一个, 未初始化的变量.
if [ "$false" ]
then
echo "\"\$false\" is true."
else
echo "\"\$false\" is false."
fi # "$false" 为假.
# 现在, 我们得到了预期的结果.
echo
exit 0
程序截图:
运行代码:
$ bash test.sh
4.(( )) 结构
(( ))
结构扩展并计算一个算术表达式的值。如果表达式的结果为0,那么返回的退出状态码为1,或者是"假"。而一个非零值的表达式所返回的退出状态码将为0,或者是 "true"
。
$ vim test.sh
输入代码:
#!/bin/bash
# 算术测试.
# (( ... ))结构可以用来计算并测试算术表达式的结果.
# 退出状态将会与[ ... ]结构完全相反!
(( 0 ))
echo "Exit status of \"(( 0 ))\" is $?." # 1
(( 1 ))
echo "Exit status of \"(( 1 ))\" is $?." # 0
(( 5 > 4 )) # 真
echo "Exit status of \"(( 5 > 4 ))\" is $?." # 0
(( 5 > 9 )) # 假
echo "Exit status of \"(( 5 > 9 ))\" is $?." # 1
(( 5 - 5 )) # 0
echo "Exit status of \"(( 5 - 5 ))\" is $?." # 1
(( 5 / 4 )) # 除法也可以.
echo "Exit status of \"(( 5 / 4 ))\" is $?." # 0
(( 1 / 2 )) # 除法的计算结果 < 1.
echo "Exit status of \"(( 1 / 2 ))\" is $?." # 截取之后的结果为 0.
# 1
(( 1 / 0 )) 2>/dev/null # 除数为0, 非法计算.
# ^^^^^^^^^^^
echo "Exit status of \"(( 1 / 0 ))\" is $?." # 1
# "2>/dev/null"起了什么作用?
# 如果这句被删除会怎样?
# 尝试删除这句, 然后在运行这个脚本.
exit 0
程序截图:
运行代码:
$ bash test.sh
二元比较操作符
1.整数比较
-eq 等于
if [ "$a" -eq "$b" ]
-ne 不等于
if [ "$a" -ne "$b" ]
-gt 大于
if [ "$a" -gt "$b" ]
-ge 大于等于
if [ "$a" -ge "$b" ]
-lt 小于
if [ "$a" -lt "$b" ]
-le 小于等于
if [ "$a" -le "$b" ]
< 小于(在双括号中使用)
(("$a" < "$b"))
<= 小于等于(在双括号中使用)
(("$a" <= "$b"))
大于(在双括号中使用)
(("$a" > "$b"))
= 大于等于(在双括号中使用)
(("$a" >= "$b"))
2.字符串比较
= 等于
if [ "$a" = "$b" ]
== 等于,与 = 等价
if [ "$a" == "$b" ]
!= 不等号
if [ "$a" != "$b" ]
< 小于,按照 ASCII 字符进行排序
if [[ "$a" < "$b" ]]
if [ "$a" \< "$b" ]
注意 "<"
使用在 [ ]
结构中的时候需要被转义
大于,按照 ASCII 字符进行排序
if [[ "$a" > "$b" ]]
if [ "$a" \> "$b" ]
注意 “>”
使用在 [ ]
结构中的时候需要被转义
-z
字符串为 “null”
,意思就是字符串长度为零
-n
字符串不为 “null”
3.算术比较与字符串比较
$ vim test.sh
输入代码:
#!/bin/bash
a=4
b=5
# 这里的"a"和"b"既可以被认为是整型也可被认为是字符串.
# 这里在算术比较与字符串比较之间是容易让人产生混淆,
#+ 因为Bash变量并不是强类型的.
# Bash允许对于变量进行整形操作与比较操作.
#+ 但前提是变量中只能包含数字字符.
# 不管怎么样, 还是要小心.
echo
if [ "$a" -ne "$b" ]
then
echo "$a is not equal to $b"
echo "(arithmetic comparison)"
fi
echo
if [ "$a" != "$b" ]
then
echo "$a is not equal to $b."
echo "(string comparison)"
# "4" != "5"
# ASCII 52 != ASCII 53
fi
# 在这个特定的例子中, "-ne"和"!="都可以.
echo
exit 0
程序截图:
运行:
4.检查字符串是否为 null
$ vim test.sh
输入代码:
#!/bin/bash
# str-test.sh: 检查null字符串和未引用的字符串,
# 使用 if [ ... ]
# 如果字符串并没有被初始化, 那么它里面的值未定义.
# 这种状态被称为"null" (注意这与零值不同).
if [ -n $string1 ] # $string1 没有被声明和初始化.
then
echo "String \"string1\" is not null."
else
echo "String \"string1\" is null."
fi
# 错误的结果.
# 显示$string1为非null, 虽然这个变量并没有被初始化.
echo
程序截图:
运行:
if [ -n "$string1" ] # 这次$string1被引号扩起来了.
then
echo "String \"string1\" is not null."
else
echo "String \"string1\" is null."
fi # 注意一定要将引用的字符放到中括号结构中!
echo
程序截图:
运行:
if [ $string1 ] # 这次, 就一个$string1, 什么都不加.
then
echo "String \"string1\" is not null."
else
echo "String \"string1\" is null."
fi
# 这种情况运行的非常好.
# [ ] 测试操作符能够独立检查string是否为null.
# 然而, 使用("$string1")是一种非常好的习惯.
#
# 就像Stephane Chazelas所指出的,
# if [ $string1 ] 只有一个参数, "]"
# if [ "$string1" ] 有两个参数, 一个是空的"$string1", 另一个是"]"
echo
程序截图:
运行:
string1=initialized
if [ $string1 ] # 再来, 还是只有$string1, 什么都不加.
then
echo "String \"string1\" is not null."
else
echo "String \"string1\" is null."
fi
# 再来试一下, 给出了正确的结果.
# 再强调一下, 使用引用的("$string1")还是更好一些, 原因我们上边已经说过了.
程序截图:
运行:
string1="a = b"
if [ $string1 ] # 再来, 还是只有$string1, 什么都不加.
then
echo "String \"string1\" is not null."
else
echo "String \"string1\" is null."
fi
# 未引用的"$string1", 这回给出了错误的结果!
exit 0
程序截图:
运行:
5.compound 和 comparison
-a
逻辑与 exp1 -a exp2 如果表达式 exp1 和 exp2 都为真的话,那么结果为真。
-o
逻辑或 exp1 -o exp2 如果表达式 exp1 和 exp2 中至少有一个为真的话,那么结果为真。
注意:这与 Bash 中的比较操作符 && 和 || 非常相像,但是这个两个操作符是用在双中括号结构中的。
[[ condition1 && condition2 ]]
-o
和 -a
操作符一般都是和 test 命令或者是单中括号结构一起使用的
if [ "$exp1" -a "$exp2" ]