条件测试结构
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" ]