When a comment leads to a syntax error in Bash

When you are writing Bash scripts and commenting out commands which are performing arithmetic operations you must be aware that they’re still interpreted in particular cases.

Let’s assume we have the following code.

if [ "${_buildonly}" == "yes" ];
then
    :#make --jobs=$((1+get_amount_of_cpus));
fi

There’s nothing wrong with the example so far. The if statement will check the value of the _buildonly variable and if it’s yes a NOP is executed. A NOP command is also known as no operation and just does nothing. In Bash you need it as a placeholder if you leave the body of a loop or if statement empty.

As programmers are not perfect and do mistakes let’s remove a closing brace ‘)’ from the arithmetic expression.

if [ "${_buildonly}" == "yes" ];
then
    :#make --jobs=$((1+get_amount_of_cpus);
fi

If this code is now executed the interpreter will be unhappy with you and raises his voice.

./installer.sh: line 244: unexpected EOF while looking for matching `)'
./installer.sh: line 255: syntax error: unexpected end of file

The reason is that the arithmetic expression in the comment is still being interpreted. The error doesn’t appear in every case. It’s showing up especially when leading spaces are left out.

So keep this in mind, always add a leading space or put the comment on its own line.

This behaviour was detected in bash 4.2.39 and zsh 5.0.0 on a x86_64 system. Other versions might or might not be affected.

I would say this is a bug. Maybe this behaviour has already been there for a (long) while. If you know some good reason for that behaviour, feel free to leave a comment.

4 Comments

  1. Gunstick

    a comment always has to be preceded by whitespace, if your if stetement would be executed you will get

    :#make: command not found

    So your nop is not a nop, but a command (which does not exist) followed by it’s parameters which have to be interpreted.

    Now if you make the parameters wrong by missing the parenthesis, then the complete if statement can’t be parsed and gives error.

  2. slopjong

    In the mentioned versions the nop worked fine with no preceded whitespace as long as there was no mathematical expression in it.

    What bash/zsh version are you using?

  3. Gunstick

    No the nop did not work. Nothing to do with math or not. It’s not a nop in the first place.

    So let’s throw some test code that you should run.

    if  true 
    then
      :#nop code (with an error
    fi
    

    => bash: syntax error near unexpected token `(‘

    if  false 
    then
      :#nop code (with an error
    fi
    

    => bash: syntax error near unexpected token `(‘

    if  true 
    then
      :#nop code without error
    fi
    

    => :#nop: command not found

    if  false 
    then
      :#nop code without error
    fi
    
    # all ok   <= yes, because it does not even try to find command ":#nop" (the if is false)
    # this does not mean that this is a nop, it's still a "command not found"
    
    
    # same test with space comment:
    if  true 
    then
      : #nop space code (with error
    fi
    
    # all ok
    
    if  false 
    then
      : #nop space code (with error
    fi
    # all ok
    
    if  true 
    then
      : #nop space code without error
    fi
    # all ok
    
    if  false 
    then
      : #nop space code without error
    fi
    # all ok
    

    Conclusion: you are wrong, I am right :-)

  4. slopjong

    To make it clear. When I removed the math expression I didn’t get a “is not command” error message and the if statement worked fine in my case while testing the condition against false and true.

    There might be differences with other bash/zsh versions as posted in the article.

    Let’s do a deal. Once I show you in real life that my script works as long as there’s no math expression, you spend me a spicy pizza :-P

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>