LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   [bash] assign boolean expression to variable (https://www.linuxquestions.org/questions/programming-9/%5Bbash%5D-assign-boolean-expression-to-variable-747543/)

hashbang#! 08-14-2009 09:40 AM

[bash] assign boolean expression to variable
 
I would like to assign true/false to $RUN in one line rather than using the clumsy if statement below.

Code:

: ${DELETE:=false}
: ${FORCE:=false}
: ${SKIP:=false}
RUN=true
if $DELETE && ! $FORCE && ! $SKIP && [ -z "$RUNDAY" ] ; then
    RUN=false
fi

I tried the following but it does not work:

Code:

RUN=! $DELETE || $FORCE || $SKIP ||  [ -n "$RUNDAY" ]

jlliagre 08-14-2009 10:26 AM

This should work:
Code:

! $DELETE || $FORCE || $SKIP || [ -n "$RUNDAY" ] && RUN=false

hashbang#! 08-14-2009 11:28 AM

Thank you for your reponse, jlliagre.

With the variables set as follows

Code:

DELETE=false
FORCE=false
SKIP=true
RUN=true

Code:

! $DELETE || $FORCE || $SKIP || [ -n "$RUNDAY" ] && RUN=false
sets RUN to false

I would have expected bash to stop evaluating as soon as the any of the sub-expressions is found true.

catkin 08-14-2009 12:07 PM

bash does not use the strings "true" and "false" to denote logical values true and false. What does it use? Here's from the "Advanced Bash-Scripting Guide 6.05"
Code:

#!/bin/bash

#  Tip:
#  If you're unsure of how a certain condition would evaluate,
#+ test it in an if-test.

echo

echo "Testing \"0\""
if [ 0 ]      # zero
then
  echo "0 is true."
else          # Or else ...
  echo "0 is false."
fi            # 0 is true.

echo

echo "Testing \"1\""
if [ 1 ]      # one
then
  echo "1 is true."
else
  echo "1 is false."
fi            # 1 is true.

echo

echo "Testing \"-1\""
if [ -1 ]    # minus one
then
  echo "-1 is true."
else
  echo "-1 is false."
fi            # -1 is true.

echo

echo "Testing \"NULL\""
if [ ]        # NULL (empty condition)
then
  echo "NULL is true."
else
  echo "NULL is false."
fi            # NULL is false.

echo

echo "Testing \"xyz\""
if [ xyz ]    # string
then
  echo "Random string is true."
else
  echo "Random string is false."
fi            # Random string is true.

echo

echo "Testing \"\$xyz\""
if [ $xyz ]  # Tests if $xyz is null, but...
              # it's only an uninitialized variable.
then
  echo "Uninitialized variable is true."
else
  echo "Uninitialized variable is false."
fi            # Uninitialized variable is false.

echo

echo "Testing \"-n \$xyz\""
if [ -n "$xyz" ]            # More pedantically correct.
then
  echo "Uninitialized variable is true."
else
  echo "Uninitialized variable is false."
fi            # Uninitialized variable is false.

echo


xyz=          # Initialized, but set to null value.

echo "Testing \"-n \$xyz\""
if [ -n "$xyz" ]
then
  echo "Null variable is true."
else
  echo "Null variable is false."
fi            # Null variable is false.


echo


# When is "false" true?

echo "Testing \"false\""
if [ "false" ]              #  It seems that "false" is just a string.
then
  echo "\"false\" is true." #+ and it tests true.
else
  echo "\"false\" is false."
fi            # "false" is true.

echo

echo "Testing \"\$false\""  # Again, uninitialized variable.
if [ "$false" ]
then
  echo "\"\$false\" is true."
else
  echo "\"\$false\" is false."
fi            # "$false" is false.
              # Now, we get the expected result.

#  What would happen if we tested the uninitialized variable "$true"?

echo

exit 0


ntubski 08-14-2009 03:25 PM

Quote:

Originally Posted by catkin (Post 3643406)
bash does not use the strings "true" and "false" to denote logical values true and false.

jlliagre's snippet executes one of the commands true or false based on the value of the variable. But I think it shoule be
Code:

$DELETE && ! $FORCE && ! $SKIP && [ -z "$RUNDAY" ] && RUN=false
or
Code:

! $DELETE || $FORCE || $SKIP || [ -n "$RUNDAY" ] || RUN=false

hashbang#! 08-15-2009 06:14 AM

ntubski, you cracked it!

However, I take catkin's point that I am not doing things the bash way. Coming from other programming languages, I find 0 = true totally counter-intuitive though.

catkin 08-15-2009 06:26 AM

Quote:

Originally Posted by hashbang#! (Post 3644239)
ntubski, you cracked it!

However, I take catkin's point that I am not doing things the bash way. Coming from other programming languages, I find 0 = true totally counter-intuitive though.

It's more (not fully!) intuitive if you consider that it's primary use is to indicate whether a command ran OK. With that perspective, it makes sense to use 0 for OK, leaving 126 other numbers (max 7 bit range less 0 and 127 reserved) to be specific about the error.

That's our perspective as problem solvers; if it worked we don't care; if it failed we are interested! :)

RaptorX 08-15-2009 07:23 AM

Quote:

Originally Posted by catkin (Post 3644248)
That's our perspective as problem solvers; if it worked we don't care; if it failed we are interested! :)

at the beginning I was startled by this 0=true thing, but once you get used to know that 0 = OK and everything else is a DETAILED error code then you cant just go back to the other way. This is more useful and actually 1=true becomes more "counter-intuitive".

:D

ntubski 08-15-2009 10:56 PM

Arithmetic Evaluation gives the more familiar 0=false C-like semantics:
Code:

DELETE=0
FORCE=0
SKIP=0
((RUN = !DELETE || FORCE || SKIP || ${#RUNDAY}))


hashbang#! 08-16-2009 05:26 AM

ntubski, I like that a lot, particularly the ${#var}!

However, the following now returns an error:

Code:

$DELETE && rm -f $RUNFILE
bash: 1: command not found

ntubski 08-16-2009 08:44 AM

Because 1 and 0 only mean true and false inside arithmetic evaluation:

Code:

((DELETE)) && rm -f $RUNFILE


All times are GMT -5. The time now is 06:54 AM.