美文网首页Shell语言用例
bash的if语句用法之:判断外部命令结果

bash的if语句用法之:判断外部命令结果

作者: CodingCode | 来源:发表于2018-10-14 10:29 被阅读3次

    如何在if语句条件表达式里面调用外部命令(函数,或者外部脚本),然后根据外部命令的执行结果确定走什么分支。

    基本语法:

    if command; then
      do-actions;
    fi
    

    含义是命令command如果执行成功,也就是返回值为0,那么执行do-actions,否则就不执行。

    反过来场景,如果命令command执行不成功,也就是返回值不为0,那么执行do-actions的格式是:

    if ! command; then
      do-actions;
    fi
    

    给一个例子:

    #!/bin/bash
    
    function foo() {
        if [ "${1}" == "YES" ]; then
            echo "It's YES"
            return 0
        else
            echo "It's not YES"
            return 1
        fi
    }
    
    if foo "YES"; then
        echo "Match: YES"
    fi
    
    if ! foo "Not YES"; then
        echo "Match: Not YES"
    fi
    

    运行结果如下:

    It's YES
    Match: YES
    It's not YES
    Match: Not YES
    

    进一步,能不能具体到不同的返回值呢

    前面例子中我们只是判断命令是否执行成功,也就是返回时是否为0,那么能不能区分具体的返回值呢,例如当返回值为1时,才执行do-actions,其他返回值2、3、...忽略呢;像:

    if command == 1; then
      do-actions
    fi
    

    我查了一些资料,遗憾的是没有找到有这样的办法,基本上只能先调用命令,然后判断返回值,像:

    command
    if [ $? - eq 1 ]; then
      do-actions
    fi
    

    或者,

    ret=command
    if [ ${ret} - eq 1 ]; then
      do-actions1
    elif [ ${ret} - eq 2 ]; then
      do-actions
    elif [ ${ret} - eq 3 ]; then
      do-actions3
    elif ...
      ...
    fi
    

    又,能不能使用输出而不是返回值判断呢

    当然是可以的,正常使用$(command)得到输出,然后比较就行了。

    #!/bin/bash
    
    function foo() {
        if [ "${1}" == "YES" ]; then
            echo "It's YES"
            return 0
        else
            echo "It's not YES"
            return 1
        fi
    }
    
    if [ "$(foo 'YES')" == "It's YES" ]; then
        echo "Match: YES"
    fi
    
    if [ "$(foo 'NO')" == "It's not YES" ]; then
        echo "Match: NO"
    fi
    

    运行结果:

    Match: YES
    Match: NO
    

    需要注意的是,判断命令输出的例子中,我们把命令的返回值丢弃了,也就是并没有判断命令是否执行成功,只判断了输出是什么。

    如果要严格判断,

    OUT1="$(foo 'YES')"
    if [ $? -eq 0 -a "${OUT1}" == "It's YES" ]; then
        echo "Match: YES"
    fi
    
    OUT2="$(foo 'NO')"
    if [ $? -eq 0 -a "${OUT2}" == "It's not YES" ]; then
        echo "Match: NO"
    fi
    

    这样运行结果:

    Match: YES
    

    此时,第二部分判断就不成立,以为$?不为0了。

    又,判断多个命令的执行

    可以使用&&和||来组合多个命令的执行。

    #!/bin/bash
    
    function foo00() { echo foo00; return 0; }
    function foo01() { echo foo01; return 0; }
    
    function foo10() { echo foo10; return 1; }
    function foo11() { echo foo11; return 1; }
    
    
    if foo00 "ppp" && foo01 "PPP"; then
        echo "case 1: pass"
    else
        echo "case 1: fail"
    fi
    
    if foo00 "ppp" && foo10 "PPP"; then
        echo "case 2: pass"
    else
        echo "case 2: fail"
    fi
    
    if foo10 "ppp" && foo01 "PPP"; then
        echo "case 3: pass"
    else
        echo "case 3: fail"
    fi
    
    if foo10 "ppp" && foo11 "PPP"; then
        echo "case 4: pass"
    else
        echo "case 4: fail"
    fi
    
    
    if foo00 "ppp" || foo01 "PPP"; then
        echo "case 1: pass"
    else
        echo "case 1: fail"
    fi
    
    if foo00 "ppp" || foo10 "PPP"; then
        echo "case 2: pass"
    else
        echo "case 2: fail"
    fi
    
    if foo10 "ppp" || foo01 "PPP"; then
        echo "case 3: pass"
    else
        echo "case 3: fail"
    fi
    
    if foo10 "ppp" || foo11 "PPP"; then
        echo "case 4: pass"
    else
        echo "case 4: fail"
    fi
    

    执行结果:

    foo00
    foo01
    case 1: pass
    foo00
    foo10
    case 2: fail
    foo10
    case 3: fail
    foo10
    case 4: fail
    foo00
    case 1: pass
    foo00
    case 2: pass
    foo10
    foo01
    case 3: pass
    foo10
    foo11
    case 4: fail
    

    又,如何用括号分组命令

    例如条件A满足,并且条件B或者条件C满足,类似:
    A && (B || )

    #!/bin/bash
    
    function foo00() { echo foo00; return 0; }
    function foo01() { echo foo01; return 0; }
    
    function foo10() { echo foo10; return 1; }
    function foo11() { echo foo11; return 1; }
    
    if foo00 && ( foo01 "BB" || foo11 "CC" ); then
        echo "case 1: pass"
    else
        echo "case 1: fail"
    fi
    
    if foo00 && ( foo10 "BB" || foo11 "CC" ); then
        echo "case 1: pass"
    else
        echo "case 1: fail"
    fi
    

    运行结果:

    foo00
    foo01
    case 1: pass
    foo00
    foo10
    foo11
    case 1: fail
    

    又,普通条件和函数混合使用

    $ cat t.sh
    #!/bin/bash
    
    
    function foo0() {
        return 0
    }
    
    function foo1() {
        return 1
    }
    
    if [ "a" == "a" ] && foo0; then echo "YES1"; fi
    if [ "a" == "a" ] && foo1; then echo "YES2"; fi
    if [ "a" == "a" ] || foo0; then echo "YES3"; fi
    if [ "a" == "a" ] || foo1; then echo "YES4"; fi
    if [ "a" == "b" ] && foo0; then echo "YES5"; fi
    if [ "a" == "b" ] && foo1; then echo "YES6"; fi
    if [ "a" == "b" ] || foo0; then echo "YES7"; fi
    if [ "a" == "b" ] || foo1; then echo "YES8"; fi
    
    $ ./t.sh
    YES1
    YES3
    YES4
    YES7
    

    这里要注意写法,用&&和||,必须用在[]括号外面,不能放里面:

    if [ "a" == "a" && foo ];
    if [ "a" == "a" -a foo ];
    

    这两种写法都是错误的。
    原因是因为[]和test是等效的,一个[]表达式和一个test是一样的,所有上述写法相当于把foo函数调用写入test语法里面,这是不通的。

    • [ expression ] == test expressio
    • expression支持与(-a),或(-o),和非(!)

    比如 [ "a" == "a" -a foo ]等价于 test "a" == "a" -a foo,这个表达式总是返回成功,不管函数foo的返回0还是1。其实在这个情况下,foo并不被认为是一个函数,而是被认为是一个字符串,和"foo"等价:
    [ "a" == "a" -a "foo" ]
    我们看test的帮助,有这个说明:

    $ man test
           -n STRING
                  the length of STRING is nonzero
    
           STRING equivalent to -n STRING
    

    也就是说此时的foo,等价于"foo",等价于 -n "foo",长度是3肯定不等于0,所以表达式总是返回true,而和函数foo没有任何关系了。

    小结

    1. if语句调用外部命令时,不要方括号'[]',而直接写命令(包括带参数)即可。
    2. 只能判断命令执行是否成功,返回值0还是非0,不能区分具体的返回值。
    3. 支持多条命令的与或操作, '&& 和 ||'
    4. 支持圆括号'()'对命令进行分组。

    相关文章

      网友评论

        本文标题:bash的if语句用法之:判断外部命令结果

        本文链接:https://www.haomeiwen.com/subject/qxkzaftx.html