魅力博客

魅力Linux|魅力空间|魅力博客|学习Linux|ubuntu日记|电脑教程|手机软件

深入学习shell脚本艺术-高级Bash脚本编程指南3



第6章 退出和退出状态
====================
exit命令被用来结束脚本,就像C语言一样.他也会返回一个值来传给父进程,父进程会判断是否
可用.

每个命令都会返回一个exit状态(有时候也叫return状态).成功返回0,如果返回一个非0值,通
常情况下都会被认为是一个错误码.一个编写良好的UNIX命令,程序,和工具都会返回一个0作为
退出码来表示成功,虽然偶尔也会有例外.

同样的,脚本中的函数和脚本本身都会返回退出状态.在脚本或者是脚本函数中执行的最后的命
令会决定退出状态.在脚本中,exit nnn命令将会把nnn退出码传递给shell(nnn必须是10进制数
0-255).

当一个脚本以不带参数exit来结束时,脚本的退出状态就由脚本中最后执行命令来决定.
 1 #!/bin/bash
 2
 3 COMMAND_1
 4
 5 . . .
 6
 7 # 将以最后的命令来决定退出状态
 8 COMMAND_LAST
 9
10 exit $?

1 #!/bin/bash
2
3 COMMAND1
4
5 . . .
6
7 # 将以最后的命令来决定退出状态
8 COMMAND_LAST

$?读取最后执行命令的退出码.函数返回后,$?给出函数最后执行的那条命令的退出码.这种给
函数返回值的方法是Bash的方法.对于脚本来说也一样.总之,一般情况下,0为成功,非0失败W.
Example 6-1 exit/exit状态
################################Start Script#######################################
 1 #!/bin/bash
 2
 3 echo hello
 4 echo $?    # 返回0,因为执行成功
 5
 6 lskdf      # 不认识的命令.
 7 echo $?    # 返回非0值,因为失败了.
 8
 9 echo
10
11 exit 113   # 将返回113给shell.
12            # To verify this, type "echo $?" after script terminates.
12            # 为了验证这个,在脚本结束的地方使用"echo $?"
################################End Script#########################################

$?对于测试脚本中的命令的结果特别有用(见Example 12-32和Example 12-17).
注意: !逻辑非操作,将会反转test命令的结果,并且这会影响exit状态.
Example 6-2 否定一个条件使用!
################################Start Script#######################################
 1 true  # true是shell内建命令,什么事都不做,就是shell返回0
 2 echo "exit status of \"true\" = $?"     # 0
 3
 4 ! true
 5 echo "exit status of \"! true\" = $?"   # 1
 6 # 注意:"!"需要一个空格
 7 #    !true   将导致一个"command not found"错误
 8 #
 9 # 如果一个命令以'!'开头,那么将使用Bash的历史机制.就是显示这个命令被使用的历史.
10
11 true
12 !true
13 # 这次就没有错误了.
14 # 他不过是重复了之前的命令(true).
################################End Script#########################################

注意事项:
    特定的退出码都有预定的含义(见附录D),用户不应该在自己的脚本中指定他.



第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#########################################


7.2 文件测试操作
----------------
返回true如果...

-e        文件存在
-a        文件存在
        这个选项的效果与-e相同.但是它已经被弃用了,并且不鼓励使用
-f        file是一个regular文件(不是目录或者设备文件)
-s        文件长度不为0
-d        文件是个目录
-b        文件是个块设备(软盘,cdrom等等)
-c        文件是个字符设备(键盘,modem,声卡等等)
-p        文件是个管道
-h        文件是个符号链接
-L        文件是个符号链接
-S        文件是个socket
-t        关联到一个终端设备的文件描述符
        这个选项一般都用来检测是否在一个给定脚本中的stdin[-t0]或[-t1]是一个终端
-r        文件具有读权限(对于用户运行这个test)
-w        文件具有写权限(对于用户运行这个test)
-x        文件具有执行权限(对于用户运行这个test)
-g        set-group-id(sgid)标志到文件或目录上
        如果一个目录具有sgid标志,那么一个被创建在这个目录里的文件,这个目录属于创建
        这个目录的用户组,并不一定与创建这个文件的用户的组相同.对于workgroup的目录
        共享来说,这非常有用.见<<UNIX环境高级编程中文版>>第58页.
-u        set-user-id(suid)标志到文件上
        如果运行一个具有root权限的文件,那么运行进程将取得root权限,即使你是一个普通
        用户.[1]这对于需要存取系统硬件的执行操作(比如pppd和cdrecord)非常有用.如果
        没有suid标志的话,那么普通用户(没有root权限)将无法运行这种程序.
        见<<UNIX环境高级编程中文版>>第58页.
           -rwsr-xr-t    1 root       178236 Oct  2  2000 /usr/sbin/pppd
        对于设置了suid的文件,在它的权限标志中有"s".
-k        设置粘贴位,见<<UNIX环境高级编程中文版>>第65页.
        对于"sticky bit",save-text-mode标志是一个文件权限的特殊类型.如果设置了这
        个标志,那么这个文件将被保存在交换区,为了达到快速存取的目的.如果设置在目录
        中,它将限制写权限.对于设置了sticky bit位的文件或目录,权限标志中有"t".
           drwxrwxrwt    7 root         1024 May 19 21:26 tmp/
        如果一个用户并不时具有stick bit位的目录的拥有者,但是具有写权限,那么用户只
        能在这个目录下删除自己所拥有的文件.这将防止用户在一个公开的目录中不慎覆盖
        或者删除别人的文件,比如/tmp(当然root或者是目录的所有者可以随便删除或重命名
        其中的文件).
-O        你是文件的所有者.
-G        文件的group-id和你的相同.
-N        从文件最后被阅读到现在,是否被修改.

f1 -nt f2
        文件f1比f2新
f1 -ot f2
        f1比f2老
f1 -ef f2
        f1和f2都硬连接到同一个文件.

!        非--反转上边测试的结果(如果条件缺席,将返回true)

Example 7-4 test死的链接文件
################################Start Script#######################################
 1 #!/bin/bash
 2 # broken-link.sh
 3 # Written by Lee bigelow <ligelowbee@yahoo.com>
 4 # Used with permission.
 5
 6 #一个真正有用的shell脚本来找出死链接文件并且输出它们的引用
 7 #以便于它们可以被输入到xargs命令中进行处理 :)
 8 #比如: broken-link.sh /somedir /someotherdir|xargs rm
 9 #
10 #这里,不管怎么说,是一种更好的方法
11 #
12 #find "somedir" -type l -print0|\
13 #xargs -r0 file|\
14 #grep "broken symbolic"|
15 #sed -e 's/^\|: *broken symbolic.*$/"/g'
16 #
17 #但这不是一个纯粹的bash,最起码现在不是.
18 #小心:小心/proc文件系统和任何的循环链接文件.
19 ##############################################################
20
21
22 #如果没对这个脚本传递参数,那么就使用当前目录.
23 #否则就使用传递进来的参数作为目录来搜索.
24 #
25 ####################
26 [ $# -eq 0 ] && directorys=`pwd` || directorys=$@
27
28 #建立函数linkchk来检查传进来的目录或文件是否是链接和是否存在,
29 #并且打印出它们的引用
30 #如果传进来的目录有子目录,
31 #那么把子目录也发送到linkchk函数中处理,就是递归目录.
32 ##########
33 linkchk () {
34     for element in $1/*; do
35     [ -h "$element" -a ! -e "$element" ] && echo \"$element\"
36     [ -d "$element" ] && linkchk $element
37     # Of course, '-h' tests for symbolic link, '-d' for directory.
37     # 当然'-h'是测试链接,'-d'是测试目录.
38     done
39 }
40
41 #如果是个可用目录,那就把每个从脚本传递进来的参数都送到linkche函数中.
42 #如果不是,那就打印出错误消息和使用信息.
43 #
44 ################
45 for directory in $directorys; do
46     if [ -d $directory ]
47     then linkchk $directory
48     else
49         echo "$directory is not a directory"
50         echo "Usage: $0 dir1 dir2 ..."
51     fi
52 done
53
54 exit 0
################################End Script#########################################
Example 28-1, Example 10-7, Example 10-3, Example 28-3, 和Example A-1 也会说明文件
测试操作的使用过程.

注意事项:
[1]        小心suid,可能引起安全漏洞,但是不会影响shell脚本.
[2]        在当代UNIX系统中,已经不使用sticky bit了,只在目录中使用.


7.3 其他比较操作
----------------
二元比较操作符,比较变量或者比较数字.注意数字与字符串的区别.

整数比较

-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"))

字符串比较
=        等于,如:if [ "$a" = "$b" ]
==        等于,如:if [ "$a" == "$b" ],与=等价
        注意:==的功能在[[]]和[]中的行为是不同的,如下:
        1 [[ $a == z* ]]    # 如果$a以"z"开头(模式匹配)那么将为true
        2 [[ $a == "z*" ]]  # 如果$a等于z*(字符匹配),那么结果为true
        3
        4 [ $a == z* ]      # File globbing 和word splitting将会发生
        5 [ "$a" == "z*" ]  # 如果$a等于z*(字符匹配),那么结果为true
        一点解释,关于File globbing是一种关于文件的速记法,比如"*.c"就是,再如~也是.
        但是file globbing并不是严格的正则表达式,虽然绝大多数情况下结构比较像.
!=        不等于,如:if [ "$a" != "$b" ]
        这个操作符将在[[]]结构中使用模式匹配.
<        小于,在ASCII字母顺序下.如:
        if [[ "$a" < "$b" ]]
        if [ "$a" \< "$b" ]
        注意:在[]结构中"<"需要被转义.
>        大于,在ASCII字母顺序下.如:
        if [[ "$a" > "$b" ]]
        if [ "$a" \> "$b" ]
        注意:在[]结构中">"需要被转义.
        具体参考Example 26-11来查看这个操作符应用的例子.
-z        字符串为"null".就是长度为0.
-n        字符串不为"null"
        注意:
        使用-n在[]结构中测试必须要用""把变量引起来.使用一个未被""的字符串来使用! -z
        或者就是未用""引用的字符串本身,放到[]结构中(见Example 7-6)虽然一般情况下可
        以工作,但这是不安全的.习惯于使用""来测试字符串是一种好习惯.[1]

Example 7-5 数字和字符串比较
################################Start Script#######################################
 1 #!/bin/bash
 2
 3 a=4
 4 b=5
 5
 6 #  这里的变量a和b既可以当作整型也可以当作是字符串.
 7 #  这里在算术比较和字符串比较之间有些混淆,
 8 #+ 因为Bash变量并不是强类型的.
 9
10 #  Bash允许对整型变量操作和比较
11 #+ 当然变量中只包含数字字符.
12 #  但是还是要考虑清楚再做.
13
14 echo
15
16 if [ "$a" -ne "$b" ]
17 then
18   echo "$a is not equal to $b"
19   echo "(arithmetic comparison)"
20 fi
21
22 echo
23
24 if [ "$a" != "$b" ]
25 then
26   echo "$a is not equal to $b."
27   echo "(string comparison)"
28   #     "4"  != "5"
29   # ASCII 52 != ASCII 53
30 fi
31
32 # 在这个特定的例子中,"-ne"和"!="都可以.
33
34 echo
35
36 exit 0
################################End Script#########################################

Example 7-6 测试字符串是否为null
################################Start Script#######################################
 1 #!/bin/bash
 2 #  str-test.sh: 测试null字符串和非引用字符串,
 3 #+ but not strings and sealing wax, not to mention cabbages and kings . . .
 4 #+ 上边这句没看懂
 5 # Using   if [ ... ]
 6
 7
 8 # 如果一个字符串没被初始化,那么它就没有定义的值(像这种话,总感觉像屁话)
 9 # 这种状态叫做"null"(与zero不同)
10
11 if [ -n $string1 ]    # $string1 没被声明和初始化
12 then
13   echo "String \"string1\" is not null."
14 else  
15   echo "String \"string1\" is null."
16 fi  
17 # 错误的结果.
18 # 显示$string1为非空,虽然他没被初始化.
19
20
21 echo
22
23
24 # 让我们再试一下.
25
26 if [ -n "$string1" ]  # 这次$string1被引用了.
27 then
28   echo "String \"string1\" is not null."
29 else  
30   echo "String \"string1\" is null."
31 fi                    # ""的字符串在[]结构中
32
33
34 echo
35
36
37 if [ $string1 ]       # 这次$string1变成"裸体"的了
38 then
39   echo "String \"string1\" is not null."
40 else  
41   echo "String \"string1\" is null."
42 fi  
43 # 这工作得很好.
44 # 这个[]test操作检测string是否为null.
45 # 然而,使用("$string1")是一种很好的习惯
46 #
47 # As Stephane Chazelas points out,
48 #    if [ $string1 ]    有1个参数 "]"
49 #    if [ "$string1" ]  有2个参数,空的"$string1"和"]"
50
51
52
53 echo
54
55
56
57 string1=initialized
58
59 if [ $string1 ]       # 再来,$string1"裸体了"
60 then
61   echo "String \"string1\" is not null."
62 else  
63   echo "String \"string1\" is null."
64 fi  
65 # 再来,给出了正确的结果.
66 # 不过怎么说("$string1")还是好很多,因为. . .
67
68
69 string1="a = b"
70
71 if [ $string1 ]       # 再来,$string1 再次裸体了.
72 then
73   echo "String \"string1\" is not null."
74 else  
75   echo "String \"string1\" is null."
76 fi  
77 # 非引用的"$string1"现在给出了一个错误的结果!
78
79 exit 0
80 # Thank you, also, Florian Wisser, for the "heads-up".
################################End Script#########################################

Example 7-7 zmore
################################Start Script#######################################
 1 #!/bin/bash
 2 # zmore
 3
 4 #使用'more'来查看gzip文件
 5
 6 NOARGS=65
 7 NOTFOUND=66
 8 NOTGZIP=67
 9
10 if [ $# -eq 0 ] # 与 if [ -z "$1" ]同样的效果
11 # 应该是说前边的那句注释有问题,$1是可以存在的,比如:zmore "" arg2 arg3
12 then
13   echo "Usage: `basename $0` filename" >&2
14   # 错误消息到stderr
15   exit $NOARGS
16   # 脚本返回65作为退出码.
17 fi  
18
19 filename=$1
20
21 if [ ! -f "$filename" ]   # 将$filename ""起来,来允许可能的空白
22 then
23   echo "File $filename not found!" >&2
24    # 错误消息到stderr
25   exit $NOTFOUND
26 fi  
27
28 if [ ${filename##*.} != "gz" ]
29 # 在变量替换中使用中括号
30 then
31   echo "File $1 is not a gzipped file!"
32   exit $NOTGZIP
33 fi  
34
35 zcat $1 | more
36
37 # 使用过滤命令'more'
38 # 如果你想的话也可使用'less'
39
40
41 exit $?   # 脚本将返回pipe的结果作为退出码
42 # 事实上,不用非的有"exit $?",但是不管怎么说,有了这句,能正规一些
43 # 将最后一句命令的执行状态作为退出码返回
################################End Script#########################################




返回顶部

发表评论:

Powered By Z-BlogPHP 1.7.3


知识共享许可协议
本作品采用知识共享署名 3.0 中国大陆许可协议进行许可。
网站备案号粤ICP备15104741号-1