本文共 3894 字,大约阅读时间需要 12 分钟。
好不容易,进入两位数的章节了... 一路走来,很辛苦吧?也很快乐吧?
在解答本章题目之前,先让我们了解一个概念:return value !我们在 shell 下跑的每一个 command 或 function ,在结束的时候都会传回父进程一个值,称为 return value 。
在 shell command line 中可用 $? 这个变量得到最"新"的一个 return value ,也就是刚结束的那个进程传回的值。
Return Value(RV) 的取值为 0-255 之间,由程序(或 script)的作者自行定议:Return Value 的作用,是用来判断进程的退出状态(exit status),只有两种:
举个例子来说明好了:
假设当前目录内有一份 my.file 的文件,而 no.file 是不存在的:$ touch my.file$ ls my.file$ echo $? # first echo0$ ls no.filels: no.file: No such file or directory$ echo $? # second echo1$ echo $? # third echo0
上例的第一个 echo 是关于 ls my.file 的 RV ,可得到 0 的值,因此为 true ﹔
第二个 echo 是关于 ls no.file 的 RV ,则得到非 0 的值,因此为 false ﹔第三个 echo 是关于第二个 echo $? 的 RV ,为 0 的值,因此也为 true 。请记住:每一个 command 在结束时都会送回 return value 的!不管你跑甚么样的命令.然而,有一个命令却是"专门"用来测试某一条件而送出 return value 以供 true 或 false的判断,它就是 test 命令了!
若你用的是 bash ,请在 command line 下打 man test 或 man bash 来了解这个 test 的用法。这是你可用作参考的最精确的文件了,要是听别人说的,仅作参考就好.
下面我只简单作一些辅助说明,其余的一律以 man 为准:
首先,test 的表示式我们称为 expression ,其命令格式有两种:test expressionor:[ expression ]( 请务必注意 [ ] 之间的空格键!)
用哪一种格式没所谓,都是一样的效果。(我个人比较喜欢后者...)
其次,bash 的 test 目前支持的测试对像只有三种:请初学者一定要搞清楚这三者的差异,因为 test 所用的 expression 是不一样的。
以 A=123 这个变量为例:* [ "$A" = 123 ]:是字符串的测试,以测试 $A 是否为 1、2、3 这三个连续的"文字"。* [ "$A" -eq 123 ]:是整数的测试,以测试 $A 是否等于"一百二十三"。* [ -e "$A" ]:是关于文件的测试,以测试 123 这份"文件"是否存在。
第三,当 expression 测试为"真"时,test 就送回 0 (true) 的 return value ,否则送出非 0 (false)。
若在 expression 之前加上一个 " ! "(感叹号),则是当 expression 为"假时" 才送出 0 ,否则送出非 0 。同时,test 也允许多重的覆合测试:例如:
[ -d "$file" -a -x "$file" ]
示例是表示当 $file 是一个目录、且同时具有 x 权限时,test 才会为 true 。
第四,在 command line 中使用 test 时,请别忘记命令行的"重组"特性,也就是在碰到 meta 时会先处理 meta 再重新组建命令行。(这个特性我在第二及第四章都曾反复强调过)。比方说,若 test 碰到变量或命令替换时,若不能满足 expression 格式时,将会得到语法错误的结果。
举例:
关于 [ string1 = string2 ] 这个 test 格式,在 = 号两边必须要有字符串,其中包括空(null)字符串(可用 soft quote 或 hard quote取得)。假如 $A 目前没有定义,或被定议为空字符串的话,那如下的写法将会失败:$ unset A$ [ $A = abc ][: =: unary operator expected
这是因为命令行碰到 $ 这个 meta 时,会替换 $A 的值,然后再重组命令行,那就变成了:
[ = abc ]
如此一来 = 号左边就没有字符串存在了,因此造成 test 的语法错误!
但是,下面这个写法则是成立的:$ [ "$A" = abc ]$ echo $?1这是因为在命令行重组后的结果为:[ "" = abc ]
由于 = 左边我们用 soft quote 得到一个空字符串,而让 test 语法得以通过... 读者诸君请务必留意这些细节哦,因为稍一不慎,将会导至 test 的结果变了个样! 若您对 test 还不是很有经验的话,那在使用 test 时不妨先采用如下这一个"法则":
虽然洋洋洒洒讲了一大堆,或许你还在嘀咕. 那. 那个 return value 有啥用啊?!
问得好!告诉你:return value 的作用可大了!若你想让你的 shell 变"聪明"的话,就全靠它了:这时候,才让我来揭晓本章的答案吧!
&& 与 || 都是用来"组建"多个 command line 用的:$ A=123$ [ -n "$A" ] && echo "yes! it's ture."yes! it's ture.$ unset A$ [ -n "$A" ] && echo "yes! it's ture."$ [ -n "$A" ] || echo "no, it's NOT ture."no, it's NOT ture.(注:[ -n string ] 是测试 string 长度大于 0 则为 true 。)上例的第一个 && 命令行之所以会执行其右边的 echo 命令,是因为上一个 test 送回了 0的 RV 值﹔但第二次就不会执行,因为为 test 送回非 0 的结果...同理,|| 右边的 echo会被执行,却正是因为左边的 test 送回非 0 所引起的。事实上,我们在同一命令行中,可用多个 && 或 || 来组建呢:$ A=123$ [ -n "$A" ] && echo "yes! it's ture." || echo "no, it's NOT ture."yes! it's ture.$ unset A$ [ -n "$A" ] && echo "yes! it's ture." || echo "no, it's NOT ture."no, it's NOT ture.怎样,从这一刻开始,你是否觉得我们的 shell 是"很聪明"的呢?
好了,最后,布置一道习题给大家做做看
下面的判断是:当 $A 被赋与值时,再看是否小于 100 ,否则送出 too big! :$ A=123$ [ -n "$A" ] && [ "$A" -lt 100 ] || echo 'too big!'too big!若我将 A 取消,照理说,应该不会送文字才对啊(因为第一个条件就不成立了)...$ unset A$ [ -n "$A" ] && [ "$A" -lt 100 ] || echo 'too big!'too big!
为何上面的结果也可得到呢?又,如何解决之呢?
(提示:修改方法很多,其中一种方法可利用第七章介绍过的 command group ...)
转载地址:http://wmzwk.baihongyu.com/