Mar 8

test和bash的小坑 不指定

felix021 @ 2013-3-8 12:57 [IT » 软件] 评论(0) , 引用(0) , 阅读(5892) | Via 本站原创 | |
昨天黄老湿问了我个问题, [ -e ] 是true还是false?为什么?

==== 啦啦啦啦啦的分割线,猜猜吧 ====

这种坑题显然只能实践出真知:
引用
$ [ -e ] && echo yes || echo no 
yes

果然坑了。

仔细想想,这个问题其实还是来源于实践的,比如一个很有可能会出现的写法是:
引用
[ -e $somefile ] && do_sth || do_sth_else

显然,在这个情况下,如果$somefile意外地是一个空串的话,bash实际上执行的就是 [ -e ] (这个可以很容易地验证),于是返回了 true。

简单过了一下源码(coreutils/src/test.c),可以看到执行流是
value = posixtest(argc - 1 <as> nargs);
    switch(nargs)
        case 1: //只有一个参数
            return one_argument();
                return argv[pos++][0] != '\0';  //检查不为空串
        case 2: //只有俩参数
            return two_arguments();
                if (argv[pos] 是 - 开头 <且> 只有俩字符 <且> 是unary_operator)
                    return unary_operator()
                        switch(argv[pos][1]):
                            case 'e':
                                unary_advance() //里面pos加了2
                                return stat(argv[pos-1], &stat_buf) == 0;
        case .. //更多参数
test_exit(value ? TEST_TRUE : TEST_FALSE);

也就是说对于只有一个参数的情况下,test只是简单地判断这个参数是否为空(无论是不是它支持的操作符),有两个参数的情况,才会去判断是否是合法操作符,再执行相应的检测。

然后才想起来,原来我还可以看manual啊,泪流满面。。。man test,果然看到这几行:
引用
-n STRING
      the length of STRING is nonzero

STRING equivalent to -n STRING

也就是说 test STRING 等于 test -n STRING ,检查非空串,于是 [ -e ] 就等于 test -n "-e",自然就是true了。。。

对于上面提到的情况来说,解决办法是在引用变量的时候,记得加上双引号,这样test就会收到2个参数,其中第二个参数是空串,stat出错,于是就可以得到(可能原先)期望的结果了:
引用
$ [ -e "$somefile" ] && echo yes || echo no
no

不过话说回来,bash脚本中引用不存在的变量这件事情本来就不应该发生,类似 rm -rf $some_path/ 这样的悲剧也不是没有发生过,但是bash又没有一个 explicit 模式,所以只能自己在使用之前检测了。

通常检测一个变量是否为空,用上面的 test -n "$VAR" 或者 test -z "$VAR" 即可(注意引号),但是如果要检测某个变量是否根本不存在,BASH却没有内建方法,只能通过这种看起来很奇怪的方式(出自stack overflow):
if [ -z "${VAR+xxx}" ]; then echo VAR is not set at all; fi

//本博客3月份真高产。。。



欢迎扫码关注:




转载请注明出自 ,如是转载文则注明原出处,谢谢:)
RSS订阅地址: https://www.felix021.com/blog/feed.php
发表评论
表情
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
记住我
昵称   密码   *非必须
网址   电邮   [注册]