专注各种脚本编程
Baidu
加入收藏夹
本站内容有下面分类知识,欢迎您的到来^_^
shell相关:指令篇 基础篇 脚本欣赏 编程实例 shell问问 shell视频教程 技巧篇 水平测试 E文资料 vi编辑器 高级Bash脚本编程指南
其他:mysql perl c语言 oracle
当前位置:| 主页>高级Bash脚本编程指南>

7.1 Test结构

百度收藏 QQ搜藏

第7章 Tests
===========
每个完整的合理的编程语言都具有条件判断的功能.Bash具有test命令,不同的[]和()操作,和
if/then结构.


7.1 Test结构
------------
一个if/then结构可以测试命令的返回值是否为0(因为0表示成功),如果是的话,执行更多命令.

有一个专用命令"["(左中括号,特殊字符).这个命令与test命令等价,但是出于效率上的考虑,
它是一个内建命令.这个命令把它的参数作为比较表达式或是文件测试,并且根据比较的结果,
返回一个退出码.

在版本2.02的Bash中,推出了一个新的[[...]]扩展test命令.因为这种表现形式可能对某些语
言的程序员来说更加熟悉.注意"[["是一个关键字,并不是一个命令.

Bash把[[ $a -lt $b ]]看作一个单独的元素,并且返回一个退出码.

((...))和let...结果也能够返回一个退出码,当它们所测试的算术表达式的结果为非0的时候,
他们的退出码将返回0.这些算术扩展(见第15章)结构被用来做算术比较.
1 let "1<2" returns 0 (as "1<2" expands to "1")
2 (( 0 && 1 )) returns 1 (as "0 && 1" expands to "0")

if命令可以测试任何命令,不仅仅是括号中的条件.
 1 if cmp a b &> /dev/null  # 阻止输出.
 2 then echo "Files a and b are identical."
 3 else echo "Files a and b differ."
 4 fi
 5
 6 # 非常有用的"if-grep" 结构:
 7 # ------------------------
 8 if grep -q Bash file
 9 then echo "File contains at least one occurrence of Bash."
10 fi
11
12 word=Linux
13 letter_sequence=inu
14 if echo "$word" | grep -q "$letter_sequence"
15 # "-q"选项是用来阻止输出
16 then
17   echo "$letter_sequence found in $word"
18 else
19   echo "$letter_sequence not found in $word"
20 fi
21
22
23 if COMMAND_WHOSE_EXIT_STATUS_IS_0_UNLESS_ERROR_OCCURRED
24 then echo "Command succeeded."
25 else echo "Command failed."
26 fi

一个if/then结构可以包含多级比较和tests.

 1 if echo "Next *if* is part of the comparison for the first *if*."
 2
 3   if [[ $comparison = "integer" ]]
 4     then (( a < b ))
 5   else
 6     [[ $a < $b ]]
 7   fi
 8
 9 then
10   echo '$a is less than $b'
11 fi

Example 7-1 什么情况下为真?
################################Start Script#######################################
  1 #!/bin/bash
  2
  3 #  技巧:
  4 #  如果你不确定一个特定的条件如何判断.
  5 #+ 在一个if-test结构中测试它.
  6
  7 echo
  8
  9 echo "Testing \"0\""
 10 if [ 0 ]      # zero
 11 then
 12   echo "0 is true."
 13 else
 14   echo "0 is false."
 15 fi            # 0 is true.
 16
 17 echo
 18
 19 echo "Testing \"1\""
 20 if [ 1 ]      # one
 21 then
 22   echo "1 is true."
 23 else
 24   echo "1 is false."
 25 fi            # 1 is true.
 26
 27 echo
 28
 29 echo "Testing \"-1\""
 30 if [ -1 ]     # -1
 31 then
 32   echo "-1 is true."
 33 else
 34   echo "-1 is false."
 35 fi            # -1 is true.
 36
 37 echo
 38
 39 echo "Testing \"NULL\""
 40 if [ ]        # NULL (控状态)
 41 then
 42   echo "NULL is true."
 43 else
 44   echo "NULL is false."
 45 fi            # NULL is false.
 46
 47 echo
 48
 49 echo "Testing \"xyz\""
 50 if [ xyz ]    # 字符串
 51 then
 52   echo "Random string is true."
 53 else
 54   echo "Random string is false."
 55 fi            # Random string is true.
 56
 57 echo
 58
 59 echo "Testing \"\$xyz\""
 60 if [ $xyz ]   # 测试$xyz是否为null,但是...(明显没人定义么!)
 61               # 只不过是一个未定义的变量
 62 then
 63   echo "Uninitialized variable is true."
 64 else
 65   echo "Uninitialized variable is false."
 66 fi            # Uninitialized variable is false.
 67
 68 echo
 69
 70 echo "Testing \"-n \$xyz\""
 71 if [ -n "$xyz" ]            # 更学究的的检查
 72 then
 73   echo "Uninitialized variable is true."
 74 else
 75   echo "Uninitialized variable is false."
 76 fi            # Uninitialized variable is false.
 77
 78 echo
 79
 80
 81 xyz=          # 初始化了,但是将其设为空值
 82
 83 echo "Testing \"-n \$xyz\""
 84 if [ -n "$xyz" ]
 85 then
 86   echo "Null variable is true."
 87 else
 88   echo "Null variable is false."
 89 fi            # Null variable is false.
 90
 91
 92 echo
 93
 94
 95 # 什么时候"flase"为true?
 96
 97 echo "Testing \"false\""
 98 if [ "false" ]              #  看起来"false"只不过是个字符串而已.
 99 then
100   echo "\"false\" is true." #+ 并且它test的结果就是true.
101 else
102   echo "\"false\" is false."
103 fi            # "false" is true.
104
105 echo
106
107 echo "Testing \"\$false\""  # 再来一个,未声明的变量
108 if [ "$false" ]
109 then
110   echo "\"\$false\" is true."
111 else
112   echo "\"\$false\" is false."
113 fi            # "$false" is false.
114               # 现在我们终于得到了期望的结果
115
116 #  如果我们test这个变量"$true"会发生什么结果?答案是和"$flase"一样,都为空,因为我
117 #+ 们并没有定义它.
118 echo
119
120 exit 0
################################End Script#########################################
练习.解释上边例子的行为(我想我解释的已经够清楚了)

 1 if [ condition-true ]
 2 then
 3    command 1
 4    command 2
 5    ...
 6 else
 7    # 可选的(如果不需要可以省去)
 8    # 如果原始的条件测试结果是false,那么添加默认的代码来执行.
 9    command 3
10    command 4
11    ...
12 fi

注意:当if和then在一个条件测试的同一行中的话,必须使用";"来终止if表达式.if和then都是
 关键字.关键字(或者命令)作为一个表达式的开头,并且在一个新的表达式开始之前,必须
 结束上一个表达式.
 1 if [ -x "$filename" ]; then

Else if和elif

elif
 elif是else if的缩减形式.
   1 if [ condition1 ]
   2 then
   3    command1
   4    command2
   5    command3
   6 elif [ condition2 ]
   7 # Same as else if
   8 then
   9    command4
  10    command5
  11 else
  12    default-command
  13 fi

使用if test condition-true这种形式和if[condition-true]这种形式是等价的.向我们前边
所说的"["是test的标记.并且以"]"结束.在if/test中并不应该这么严厉,但是新版本的Bash
需要它.

注意:test命令是Bash的内建命令,用来测试文件类型和比较字符串.因此,在Bash脚本中,test
并不调用/usr/bin/test的二进制版本(这是sh-utils工具包的一部分).同样的,[并不调用
/usr/bin/[,被连接到/usr/bin/test.
  bash$ type test
  test is a shell builtin
  bash$ type '['
  [ is a shell builtin
  bash$ type '[['
  [[ is a shell keyword
  bash$ type ']]'
  ]] is a shell keyword
  bash$ type ']'
  bash: type: ]: not found

Example 7-2 几个等效命令test,/usr/bin/test,[],和/usr/bin/[
################################Start Script#######################################
  1 #!/bin/bash
  2
  3 echo
  4
  5 if test -z "$1"
  6 then
  7   echo "No command-line arguments."
  8 else
  9   echo "First command-line argument is $1."
 10 fi
 11
 12 echo
 13
 14 if /usr/bin/test -z "$1"      # 与内建的test结果相同
 15 then
 16   echo "No command-line arguments."
 17 else
 18   echo "First command-line argument is $1."
 19 fi
 20
 21 echo
 22
 23 if [ -z "$1" ]                # 与上边代码的作用相同
 24 #   if [ -z "$1"                应该工作,但是...
 25 #+  Bash相应一个缺少关闭中括号的错误消息.
 26 then
 27   echo "No command-line arguments."
 28 else
 29   echo "First command-line argument is $1."
 30 fi
 31
 32 echo
 33
 34
 35 if /usr/bin/[ -z "$1" ]       # 再来一个,与上边代码的作用相同
 36 # if /usr/bin/[ -z "$1"       # 工作,但是给个错误消息
 37 #                             # 注意:
 38 #                               This has been fixed in Bash, version 3.x.
 38 #                               在ver 3.x上,这个bug已经被Bash修正了.
 39 then
 40   echo "No command-line arguments."
 41 else
 42   echo "First command-line argument is $1."
 43 fi
 44
 45 echo
 46
 47 exit 0
###############################End Script#########################################

[[]]结构比Bash的[]更加灵活,这是一个扩展的test命令,从ksh88继承过来的.
注意:在[[]]结构中,将没有文件扩展或者是单词分离,但是会发生参数扩展和命令替换.
 1 file=/etc/passwd
 2
 3 if [[ -e $file ]]
 4 then
 5   echo "Password file exists."
 6 fi
注意:使用[[]],而不是[],能够阻止脚本中的许多逻辑错误.比如,尽管在[]中将给出一个错误,
 但是&&,||,<>操作还是能够工作在一个[[]]test之中.
注意:在if后边,test命令和[]或[[]]都不是必须的.如下:
 1 dir=/home/bozo
 2
 3 if cd "$dir" 2>/dev/null; then   # "2>/dev/null" hides error message.
 4   echo "Now in $dir."
 5 else
 6   echo "Can't change to $dir."
 7 fi
if命令将返回if后边的命令的退出码.

与此相似,当在一个在使用与或列表结构的时候,test或中括号的使用,也并不一定非的有if不可
 1 var1=20
 2 var2=22
 3 [ "$var1" -ne "$var2" ] && echo "$var1 is not equal to $var2"
 4
 5 home=/home/bozo
 6 [ -d "$home" ] || echo "$home directory does not exist."

(())结构扩展并计算一个算术表达式的结果.如果表达式的结果为0,它将返回1作为退出码,或
者是"false".而一个非0表达式的结果将返回0作为退出码,或者是"true".

Example 7-3 算数测试使用(( ))
################################Start Script#######################################
 1 #!/bin/bash
 2 # 算数测试
 3
 4 # The (( ... )) construct evaluates and tests numerical expressions.
 4 # (( ... ))结构计算并测试算数表达式的结果.
 5 # 退出码将与[ ... ]结构相反!
 6
 7 (( 0 ))
 8 echo "Exit status of \"(( 0 ))\" is $?."         # 1
 9
10 (( 1 ))
11 echo "Exit status of \"(( 1 ))\" is $?."         # 0
12
13 (( 5 > 4 ))                                      # true
14 echo "Exit status of \"(( 5 > 4 ))\" is $?."     # 0
15
16 (( 5 > 9 ))                                      # false
17 echo "Exit status of \"(( 5 > 9 ))\" is $?."     # 1
18
19 (( 5 - 5 ))                                      # 0
20 echo "Exit status of \"(( 5 - 5 ))\" is $?."     # 1
21
22 (( 5 / 4 ))                                      # 除法也行
23 echo "Exit status of \"(( 5 / 4 ))\" is $?."     # 0
24
25 (( 1 / 2 ))                                      # 出发结果<1
26 echo "Exit status of \"(( 1 / 2 ))\" is $?."     # 结果将为0
27                                                  # 1
28
29 (( 1 / 0 )) 2>/dev/null                          # 除数为0的错误
30 #           ^^^^^^^^^^^
31 echo "Exit status of \"(( 1 / 0 ))\" is $?."     # 1
32
33 # What effect does the "2>/dev/null" have?
33 # "2>/dev/null"的作用是什么?
34 # 如果删除"2>dev/null"将会发生什么?
35 # Try removing it, then rerunning the script.
35 # 尝试删除它,然后再运行脚本.
36
37 exit 0
################################End Script#########################################

上一篇:6.退出和退出状态 下一篇:7.2 文件测试操作

power by soyo123 2007-2008