9

I'm new to shell programming, and noticed that the following is accepted:

if [ $table = "Session" ]; then continue; fi 

And so is the following:

if [ $table = "Session" ]; then continue; fi 

While the following produces a syntax error:

if [ $table = "Session" ]; then; continue; fi 

Why is the then keyword different from the others?

1
  • This looks like a problem in the shell to me. Replace the ; with a newline and it works. Otoh, omit the line with continue and you get the error. Read the source, Ben. Commented Sep 24, 2013 at 23:14

2 Answers 2

14

Because then is neither a command nor a shell builtin, but actually a part of the if syntax. From man bash:

 if list; then list; [ elif list; then list; ] ... [ else list; ] fi The if list is executed. If its exit status is zero, the then list is executed. Otherwise, each elif list is executed in turn, and if its exit status is zero, the corresponding then list is executed and the command completes. Otherwise, the else list is executed, if present. The exit status is the exit sta‐ tus of the last command executed, or zero if no condition tested true. 

So this:

if [ $table = "Session" ]; then continue; fi 

works because both [ $table = "Session" ] and continue are commands that can stand alone; they make up the respective list part of the if command. Just paste those into an interactive shell and you will see that they won't cause any syntax errors:

martin@martin:~$ export table=test martin@martin:~$ [ $table = "Session" ] martin@martin:~$ continue bash: continue: only meaningful in a `for', `while', or `until' loop 

On the other hand, then is not a real command that can stand on its own:

martin@martin:~$ then bash: syntax error near unexpected token `then' 

So in the first two examples, you're using if just like the man page describes it:

if list; then list; fi 

But if you put a ; behind then, bash will see this as a syntax error. Admittedly, shell syntax can seem quite confusing sometimes, especially when you're just getting into it. I remember being very confused about the fact that it requires spaces around [ and ], but once you realize that [ is actually a command or shell builtin, it's comprehensible. :)

7

You need to put a semicolon after a command. [ … ] is a command, as is continue. On the other hand, if, then and fi are not commands: they are reserved words.

if looks like a command, but that's because it's almost always followed by exactly one command. It is valid to write

if print_table_value >foo; [ "$(cat foo)" = "Session" ]; then … 

which can also be presented in a number of ways such as

if print_table_value >foo [ "$(cat foo)" = "Session" ] then … 

The general syntax of a conditional command is

 if compound-list then compound-list (elif compound-list then compound-list)* (else compound-list then compound-list)? fi 

where

  • The line breaks are for readability only.
  • A compound-list is a list of commands, each terminated by a ; or newline.
  • (…)? indicates an optional part and (…)* indicates a part that can be repeated 0, 1 or many times.

Keywords are only recognized as such at the beginning of a command.

A conditional command has to end with the keyword fi. This does not remove the need to follow it by an operator if some other command appears after it; for example, if the conditional is to be followed by another command, then there needs to be a ; or newline in between; if the conditional is to be executed in the background, then it needs to be followed by &, etc.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.