0

This doesn't work, and every time executes the else clause:

state=false
function toggle {
  if [ ! $state ]
  then
    echo first
    state=true
  else
    echo second
    state=false
  fi
}

I'd expect calling toggle multiple times would have alternating output between "first" and "second", but instead I only get "second"

theonlygusti
  • 11,032
  • 11
  • 64
  • 119

4 Answers4

2

test doesn't use the strings true and false for boolean values. test treats any non-empty string as true, and an empty string as false.

You need to perform explicit comparisons:

state=false
function toggle {
  if [ "$state" = false ]
  then
    echo first
    state=true
  else
    echo second
    state=false
  fi
}
Barmar
  • 741,623
  • 53
  • 500
  • 612
0

Both true and false are, in your case, just strings, which evaluate to the logical true.

So regardless on whether state contains the word true or false, [ ! $state ] will always revert to the logical false -- triggering your else clause.

Since you are already using true and false, there is something you can do: Both true and false are valid shell commands that do nothing but return an error code of 0 and 1, respectively. Since if basically evaluates a command (look it up, [ is an executable) and uses their error code, you could do something like this:

if $state; 

$state would be either false or true, which would then be executed by if, and, depending on the error code, select which specific code block of the if ... else ... fi block would be executed.

chw21
  • 7,970
  • 1
  • 16
  • 31
  • `-eq` is for numbers, `=` is for strings. – Barmar Dec 09 '16 at 02:33
  • You're right, I made something completely different anyway ;) – chw21 Dec 09 '16 at 02:35
  • While this works, I suggest you make it clearer that this _only_ works as intended with `$state` values of `false` and `true`, and that the approach relies on executing the variable value - whatever it happens to be - _as a command_. – mklement0 Dec 09 '16 at 02:42
  • I think I made it clearer. The solution of @Barmar probably still is much easier to understand, so I've also upvoted his. – chw21 Dec 09 '16 at 02:51
0

I don't know where it went, but my favourite answer seems to have disappeared.

state=
function toggle {
  if [ ! $state ]
  then
    echo first
    state=true
  else
    echo second
    state=
  fi
}
theonlygusti
  • 11,032
  • 11
  • 64
  • 119
0

BASH 4+ version as a function :

# -- Toggle between TRUE and FALSE with a variable every time called --
# Globals: None
# Arguments: boolean (pass in previous)
# Returns: boolean (switched value)
# --
toggle_true_false() {
    toggle="${1}"
    if [[ -z ${toggle} ]] || [[ ${toggle} = false ]] ; then
        toggle=true
    else
        toggle=false
    fi
    echo ${toggle}
}

How to use it :

local toggle
while [[ 1 ]] ; do
    toggle=$(toggle_true_false ${toggle})
    if ${toggle} ;then echo "value is TRUE" ;else echo "value is FALSE" ;fi
done

Basically we declare a variable and then call the function that will reverse it's value and store it back in the variable. Then you can call some other command based on the value of this toggle value..

Output:

value is TRUE
value is FALSE
value is TRUE
value is FALSE
value is TRUE
value is FALSE
value is TRUE
....

Further reading : Dealing with boolean: How to declare and use boolean variables in shell script? and how to use functions: Passing parameters to a Bash function

Mike Q
  • 6,716
  • 5
  • 55
  • 62