Understanding Bash short-circuiting

前端 未结 2 1101
一生所求
一生所求 2020-12-07 04:26

First of all I\'m not a Bash pro. I discovered few months ago that if I use both the && and || short circuit operators in sequence with cur

相关标签:
2条回答
  • 2020-12-07 04:46

    Mr. Llama already corectly answered the question, this only for a quick reference what happens for different "combinations". The cmd0 is an "command" with zero-exit status and the cmd1 is with nonzero.

    cmd0() { echo -n "[$@-0]"; return 0; }
    cmd1() { echo -n "[$@-1]"; return 1; }
    second() { echo "[second]"; }
    
    doit() { echo "case: $@"; eval "$@"; echo; }
    
    doit 'cmd0 start && cmd0 first && second'
    doit 'cmd0 start && cmd0 first || second'
    doit 'cmd0 start || cmd0 first && second'
    doit 'cmd0 start || cmd0 first || second'
    
    doit 'cmd0 start && cmd1 first && second'
    doit 'cmd0 start && cmd1 first || second'
    doit 'cmd0 start || cmd1 first && second'
    doit 'cmd0 start || cmd1 first || second'
    
    doit 'cmd1 start && cmd0 first && second'
    doit 'cmd1 start && cmd0 first || second'
    doit 'cmd1 start || cmd0 first && second'
    doit 'cmd1 start || cmd0 first || second'
    
    doit 'cmd1 start && cmd1 first && second'
    doit 'cmd1 start && cmd1 first || second'
    doit 'cmd1 start || cmd1 first && second'
    doit 'cmd1 start || cmd1 first || second'
    

    produces:

    case: cmd0 start && cmd0 first && second
    [start-0][first-0][second]
    
    case: cmd0 start && cmd0 first || second
    [start-0][first-0]
    
    case: cmd0 start || cmd0 first && second
    [start-0][second]
    
    case: cmd0 start || cmd0 first || second
    [start-0]
    
    case: cmd0 start && cmd1 first && second
    [start-0][first-1]
    
    case: cmd0 start && cmd1 first || second
    [start-0][first-1][second]
    
    case: cmd0 start || cmd1 first && second
    [start-0][second]
    
    case: cmd0 start || cmd1 first || second
    [start-0]
    
    case: cmd1 start && cmd0 first && second
    [start-1]
    
    case: cmd1 start && cmd0 first || second
    [start-1][second]
    
    case: cmd1 start || cmd0 first && second
    [start-1][first-0][second]
    
    case: cmd1 start || cmd0 first || second
    [start-1][first-0]
    
    case: cmd1 start && cmd1 first && second
    [start-1]
    
    case: cmd1 start && cmd1 first || second
    [start-1][second]
    
    case: cmd1 start || cmd1 first && second
    [start-1][first-1]
    
    case: cmd1 start || cmd1 first || second
    [start-1][first-1][second]
    
    0 讨论(0)
  • 2020-12-07 05:03

    This is actually a very common Bash pitfall. It is not a bug.

    returnNumber 0 evaluates to true, so the second block (joined by logical and &&) is evaluated as well to make sure the result of first && second is still true.
    The second block outputs OK but evaluates to false, so now the result of first && second is false. This means that the third portion (joined by logical or ||) must be evaluated as well, causing NG to be displayed as well.


    Instead of relying on && and ||, you should be using if statements:

    if returnNumber 0; then
        echo 'OK'
        returnNumber 1
    else
        echo 'NG'
    fi
    

    tl;dr: Never use x && y || z when y can return a non-zero exit status.

    0 讨论(0)
提交回复
热议问题