Print condition result directly in bash without using if

22,380

Solution 1

In this case you can use the list control operators && and || instead:

[[ $# -eq 0 ]] && echo false || echo true

[[ $# -eq 0 ]] && { echo false; } \
               || { echo true; }

The { } group a list of commands, you don't need them for just a single command, but they often make such constructions more readable (though a list also requires a terminating ; or newline).

As noted by @Kusalananda, this works for simple code (like echo) where commands return 0 ("true"): despite the lexical similarity the above does not have the same semantics as a short-circuited evaluation in C does, i.e.:

(argc==1) && printf("false\n") || printf("true\n");  /* C, not bash */

A workaround where the command(s) might return a non-zero status is:

[[ $# -eq 0 ]] && { echo false;:; } || { echo true; }

where the extra ":" null command at the end of the first list ensures that it returns a 0 (true) status (the return status of a list is the exit status of the last command executed in the list).

Though note the logic above is the inverse of an ordinary conditional logic test in order to match the question, the usual logic is

[[ boolean-condition ]] && { true-actions;:; } || { false-actions; }

or, to be clearer for this example:

[[ $# -eq 0 ]] && { echo no arguments;:; } || { echo found arguments; }

When you have two (or another defined number of states), you can also use an array with a computed index, as shown in Stéphane's answer:

declare -a bool=([1]=true [0]=false)
echo ${bool[ (($# == 0)) ]}

or

temperature=70
declare -a porridge=([1]="too hot" [2]="just right" [3]="too cold")
echo ${porridge[ (( temperature >= 75 ? 1 :
                    temperature <= 68 ? 3 : 2 )) ]}

This uses arithmetic expressions within (( )), where 0 is false, opposite to the usual shell convention.

Solution 2

You can use $? that keeps the exit code of the last executed command:

echo "Are there any arguments?"
[ $# -eq 0 ]
echo $?

Solution 3

You can do something like:

bool=(false true)
echo "${bool[$# != 0]}"

(assuming ksh93, bash or zsh in ksh emulation).

In any POSIX shell,

echo "$(($# != 0))"

will output 1 for true and 0 for false.

Solution 4

Since I can't post comments yet (insufficient rep), I'll point out in a new answer that mr-spuratic's solution also works with single brackets, like so:

[ $# -eq 0 ] && { echo false; } || { echo true; }
Share:
22,380

Related videos on Youtube

ctomek
Author by

ctomek

Updated on September 18, 2022

Comments

  • ctomek
    ctomek almost 2 years

    Let's say I have this simple code:

    echo "Are there any arguments?"
    if [ $# -eq 0 ]; then
        echo "false"
    else
        echo "true"
    fi
    

    As you can see it would be better to just have opportunity to directly print condition result, but I don't know how to do it.

    It would be something like:

    echo "$([ $# -eq 0 ])"

    But it doesn't work that way. Can we do this without if?

    • Admin
      Admin almost 7 years
      You can try zsh. Zsh will change PS1 color (command prompt color) according to $?(the return value of the last command). imgur.com/a/yBz2H
  • Kusalananda
    Kusalananda over 5 years
    But note that the semantics of the statements are slightly altered by this. The last command will be executed if either of the previous commands returned a non-zero exit status. This means that using ... && ... || ... is not generally a good replacement for if ...; then ...; else ...; fi.
  • mloureiro
    mloureiro almost 3 years
    isn't the other way around? "&&" for true and "||" for false? I'm testing locally and [[ 0 = 0 ]] && echo false || echo true returns false
  • mr.spuratic
    mr.spuratic almost 3 years
    @mloureiro - yes you are correct, I have updated to clarify, but this is the condition the OP requested... "Are there any arguments?" is false when the condition $# -eq 0 is true.
  • mloureiro
    mloureiro almost 3 years
    My bad, you're right. It is confusing returning the opposite, but it was what OP requested.
  • Admin
    Admin about 2 years
    Just remember that "true" and "false" are BASH boolean values, and "0" and "1" are not. this works: if "true"; then, while this gives an error: if "0"; then.
  • Admin
    Admin about 2 years
    Just remember that "true" and "false" are BASH boolean values, and "0" and "1" are not. this works: if "true"; then, while this gives an error: if "0"; then.
  • Admin
    Admin about 2 years
    @hoijui, 0 and non-zero are false and true (as in most languages) in the arithmetic expressions of POSIX/Korn-like shells including bash. $(( x == x )) expands to 1. $(( 1 == 2 )) expands to 0. if (( 1 )); then echo yes; fi outputs yes. false and true are two commands which some shells including bash also have builtin that return 1 and 0 respectively in their exit status. An exit status of 0 means true/success, and anything else false/failure with the actual value used to discriminate between different types of failures, in shells (bash or otherwise) or not. ((0)) exits with 1