bash: syntax error near unexpected token `}'

25,821

Solution 1

[ is just another character, according to bash; it's not self-delimiting. So you need to put spaces around [ and ]. Although you'd be better off using [[ and ]].

And the command following if (yes, [ is a command) must be terminated with a ; or a newline.

Finally, == (which is not posix, FWIW; posix prefers =) is string equality, not numeric equality.

So you might have meant:

if [[ $a -eq 1 ]]; then echo yes; fi

But you could use arithmetic evaluation instead:

if ((a == 1)); then echo yes; fi

(In arithmetic evalution, equality is ==, and you don't need $ before variable names. I know it's confusing.)

For more information about [: help test. About [[: help [[ (which builds on test). About ((: help let. About bash: man bash

Solution 2

Summary

Use:

if [ "$a" = 1 ]; then echo yes; fi

Full answer

The error reported by bash: -bash: syntax error near unexpected token `}' is an attempt to guide the code writer to the error, but bash can easily get it wrong and signal an error where it isn't.

Actually, there are several errors in the code. But let's reproduce the error that bash reports in a simpler code line:

$ if true then { true; } fi;
bash: syntax error near unexpected token `}'

If the line changes a little, the error is reported at about the same place but a little different:

$ if true then true; fi;
bash: syntax error near unexpected token `fi'

And, this also report an error:

$ if true; then; true; fi;
bash: syntax error near unexpected token `;'

All of that happens because the syntax required (copied from the manual) is:

if list; then list; fi;

where list is one or several simple commands (or pipes, or compound commands) that end in a newline or a semicolon. Note that, in general, a newline could be replaced with a semicolon and viceversa.

This is valid (no syntax error reported)

if   true;   then   true;   fi

This is also valid:

if     true
then   true
fi

or:

if echo start; true; then echo decision; true; echo next; fi;

Or other variations of newlines and/or semicolons.

Of course, the last semicolon is not required but not forbidden.

Additionally, the [ and ] require (usually) spaces to be differentiated by bash as words (tokens) and therefore be understood as a test

if [ $a == 1 ]; then { echo 'yes'; } fi;       # still subtly incorrect.

But, also, a variable expansion should be quoted ("$a"), the == is valid in bash, but it may be invalid in some other shells, so we rather should use a = inside single [ ], the 'yes' technically doesn't need to be quoted (even if it is no harmful), and the braces { } are not needed for a single simple command, all that makes this a better version:

if [ "$a" = 1 ]; then echo yes; fi

Or, if you choose to use bash/ksh/zsh [[ ]]:

if [[ $a == 1 ]]; then echo yes; fi

And, lastly, the test with either = or == is a string comparison, not numerical, so +1 would not be equal to 1 even if they are in value. To test numerically, you could use -eq.

Solution 3

[ is a command in Bash, just like any of the other commands such as if, while, etc. You can see this if you double check the man page:

$ man [
NAME
       bash, :, ., [, alias, bg, bind, break, builtin, caller, cd, command, .....

You can also tell it's a real command with this example:

$ type -a [
[ is a shell builtin
[ is /usr/bin/[

The first result is the builtin version of [ that's part of Bash. The second is the version of [ that's included with the GNU coreutils.

On Fedora you can see what RPM it's a part of:

$ rpm -qf /usr/bin/[
coreutils-8.5-7.fc14.x86_64

Given this you need to make sure that there are spaces around any commands so that they get parsed correctly.

Doing this:

$ if [$a == 1] ...

Would be identical to this:

$ lsblah
bash: lsblah: command not found...

The ls command cannot be parsed correctly because it isn't buffered with spaces so that it's parse-able.

Share:
25,821

Related videos on Youtube

Michael Durrant
Author by

Michael Durrant

rails ruby rspec rock

Updated on September 18, 2022

Comments

  • Michael Durrant
    Michael Durrant almost 2 years

    I tried using this:

    $ if [$a == 1] then { echo 'yes'; } fi;
    

    but I get an error:

    -bash: syntax error near unexpected token `}'
    

    What is the correct format? I tried several with no luck.

    • Admin
      Admin almost 11 years
      you write bash not csh
    • Admin
      Admin almost 11 years
    • Admin
      Admin over 4 years
      I noticed later that you also miss a space in the syntax of both square brackets. The correct condition syntax is: [ $a == 1 ] instead of [$a == 1]. Of course, it is recommended to use a separate equals sign = rather than a double sign ==. The two signs represent "bashism" (applicable only in some Shell). More info about double or single equal signs, for example, here: unix.stackexchange.com/questions/72039/… And also for POSIX syntax, it is better to use the -eq comparison operator instead of =.
    • Admin
      Admin over 4 years
      @s3n0, notice that we have existing answers, one of them accepted. Please use comments on the Question to clarify the question, not to Answer it. Thank you!
  • Honey
    Honey over 4 years
    the man [ is extremely informative. It's also interesting to know that [ is a command and has its own man page...
  • Stefan Skoglund
    Stefan Skoglund over 4 years
    @Honey The bourne shell doesn't originally have a built-in test/[ function. The shell's if function takes it decision from $? after running test/[ .