7

I have a problem with boolean for while loop. As such, I switch to for loop instead. But still, I cannot change the value of a boolean after the condition is met.

doFirst= true
    for (( j=1; j<=7; j++))
    do
            letter="A"
            seatChoses=$letter$j

            flagRand=$(echo $flightSeatBooked | awk -v flseatRand=$flightSeatBooked -v orseatRand=$seatChoses '{print match(flseatRand, orseatRand)}')
            if  $doFirst ; then
            **$doFirst= false** // Here is the error!
                if [ $flagRand -eq 0 ]; then
                    echo "System generated a slot, "$seatChoses" for you. [Y or N]"
                fi
            fi

    done
4
  • 1
    Tried removing the $? doFirst = false Commented Nov 25, 2012 at 6:26
  • In your echo, you don't need the quotes around $seatChoses.
    – siride
    Commented Nov 25, 2012 at 6:27
  • Hi Anders, I am actually accessing the same variable as declared in the first line... Can I still remove the $?
    – Bryan Wong
    Commented Nov 25, 2012 at 6:43
  • The line marked 'here is the error' should read (no spaces) doFirst=false. No $. It's still an aconventional way of doing business, but it will at least work. Commented Nov 25, 2012 at 7:02

2 Answers 2

21

There is no such thing as a boolean value in a shell script (that is, something you can store in a variable, and treat as a boolean). true and false are commands; true exits with value 0, and false exits with a nonzero value. An if statement in bash taks a command; if that command returns 0, then the then clause is executed, otherwise the else clause is.

doFirst= true

This line doesn't do what you expect at all. In a shell script, you cannot have any spaces after the equals sign. The space means you're done with the assignment, and now writing a command. This is equivalent to:

doFirst="" true

Furthermore, if you have an assignment before a command (like this), that doesn't actually perform the assignment in the shell. That sets that environment variable in the environment for that command alone; the assignment has no effect on anything outside of that command.

if  $doFirst ; then

This expands the $doFirst variable, and tries to interpret the result as a command. Oddly, if $doFirst is undefined (which it is, as I explain above), this takes the then branch. At that point, you make your first mistake again, trying to set a variable to be false, and again, nothing happens; $doFirst is left undefined. You make the further mistake of trying to assign $doFirst; you use $ to get the value of a variable, when setting, you use the bare name.

My recommendation would be to not try to use booleans in Bash; just use strings instead, and check the value of the string. Note that I remove the space, so now I'm setting it to that exact string; and there is no command, so this sets the variable within the shell, not in the environment for a single command:

doFirst=true
# ...
   if [ $doFirst = true ]; then
       doFirst=false
   # ...
5
  • Hi @Brian, Thanks the for coaching. However, it came out this error for your 3rd line. How do I explain? [: true: integer expression expected
    – Bryan Wong
    Commented Nov 25, 2012 at 6:55
  • 1
    @BryanWong Sorry, use == instead of -eq; -eq is for numbers, == is for strings. Edited my answer. Commented Nov 25, 2012 at 7:01
  • @BrianCampbell: Bash does, in fact, have booleans. I was skeptical at first, but I did some sleuthing. You can try it yourself. The if-statement behaves as a boolean, not as a string that's either set or unset.
    – siride
    Commented Nov 25, 2012 at 15:57
  • 1
    @siride The if statement acts on a boolean, but on the return value of the command you pass, not on the string value of a variable. So, Bash has boolean return values (though with the somewhat counterintuitive mapping of 0 to true and any nonzero value to false), but you can't store the return value in a variable and then test it directly with if; you would need to use if [ $var -eq 0 ], which is running the [ (or test) command, and checking the return value of that command. Essentially, Bash has boolean exit codes, but no boolean variables. Commented Nov 25, 2012 at 16:08
  • @siride It can be somewhat confusing, because it does have true and false, and operators like && and ||. true and false are commands, which return 0 and non-zero; and && and || operate based on the exit codes of commands. So you can write if true && false; then ..., and it works. But you can't store that. foo=$(true) stores the standard out of true in foo, not the return value. true; foo=$? stores the return value; but you can't then say if $foo; then .... Commented Nov 25, 2012 at 16:14
2

Are you actually putting a space between the = and the "true"/"false" or is that a formatting error? That's one of your problems.

Another, as mentioned by Anders Lindahl in the comment section, is that when you set a variable in shell scripting, you cannot use the $ in the front. You must say

doFirst=false

Again, note that there are no spaces around the equals sign.

2
  • Hi siride, I am actually accessing the same variable as declared in the first line... Can I still remove the $?
    – Bryan Wong
    Commented Nov 25, 2012 at 6:45
  • 3
    You use $ when reading variables, not when assigning the variable. E.g. doFirst=false versus if $doFirst.
    – Barmar
    Commented Nov 25, 2012 at 6:46

Not the answer you're looking for? Browse other questions tagged or ask your own question.