Invert boolean variable
There are two errors in your script. The first is that you need a space between !
and $flag
, otherwise the shell looks for a command called !$flag
. The second error is that -eq
is for integer comparisons, but you're using it on a string. Depending on your shell, either you'll see an error message and the loop will continue forever because the condition [ "$x" -eq "true" ]
cannot be true, or every non-integer value will be treated as 0 and the loop will exit if you enter any string (including false
) other than a number different from 0.
While ! $flag
is correct, it's a bad idea to treat a string as a command. It would work, but it would be very sensitive to changes in your script, since you'd need to make sure that $flag
can never be anything but true
or false
. It would be better to use a string comparison here, like in the test below.
flag=false
while [ "$flag" != "true" ]
do
read x
if [ "$x" = "true" ]
then
flag=true
fi
echo "${x} : ${flag}"
done
There's probably a better way to express the logic you're after. For example, you could make an infinite loop and break it when you detect the termination condition.
while true; do
read -r x
if [ "$x" = "true" ]; then break; fi
echo "$x: false"
done
While there are no Boolean variables in Bash, it is very easy to emulate them using arithmetic evaluation.
flag= # False
flag=0 # False
flag=1 # True (actually any integer number != 0 will do, but see remark below about toggling)
flag="some string" # Maybe False (make sure that the string isn't interpreted as a number)
if ((flag)) # Test for True
then
: # do something
fi
if ! ((flag)) # Test for False
then
: # do something
fi
flag=$((1-flag)) # Toggle flag (only works when flag is either empty or unset, 0, 1, or a string which doesn't represent a number)
This also works in ksh. I wouldn't be surprised if it works in all POSIX-compliant shells, but haven't checked the standard.
If you can be absolutely sure that the variable will contain either 0 or 1, you can use the bitwise XOR-equal operator to flip between the two values:
$ foo=0
$ echo $foo
0
$ ((foo ^= 1))
$ echo $foo
1
$ ((foo ^= 1))
$echo $foo
0