cerule
cerule

Reputation: 45

When do if constructs not require brackets?

I'm doing some homework for a shell scripting class and had a question asking me to write a script that tests whether or not the argument entered is a valid shell variable name. The below script seems to work fine.

if echo "$1" | grep -v ".*[^A-Za-z_]" > /dev/null
then
        echo yes
else
        echo no
fi

I understand brackets are short hand for the test function in the BASH shell. My problem is that, when I attempted the above script using brackets I got an error.

if [ echo "$1" | grep -v ".*[^A-Za-z_]" > /dev/null ]

The problem with this (I believe) is that grep is trying to use the ] as its argument, thus resulting in an error when the script is run.

In what situations do I not need brackets?

Upvotes: 2

Views: 151

Answers (3)

Jotne
Jotne

Reputation: 41456

You may also use double square brackets [[ instead of single [

Read more about it here: http://mywiki.wooledge.org/BashFAQ/031:

[ ("test" command) and [[ ("new test" command) are used to
evaluate expressions. [[ works only in Bash, Zsh and the Korn shell,
and is more powerful; [ and test are available in POSIX shells

Upvotes: 1

Etan Reisner
Etan Reisner

Reputation: 80931

[/test is a command (also a built-in), as you said. It is a command that accepts arguments of a specific sort and behaves in a specific way given those arguments.

It accepts flags and comparison operators and operates on those to obtain a true or false result. It then translates that result into a return code. 0 for true and 1 for false.

The if construct in the shell is defined

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 status of the last command executed, or zero if no condition tested true.

So when [/test returns an exit code that is what if evaluates.

The reason you don't need (and can't use) [ around the echo command/pipeline is because that isn't a valid set of [ arguments. Instead that is a command list itself and, as such, does not need to be evaluated by [. You can simply use it directly and have the return code of the pipeline handed to if for evalution.

Upvotes: 2

Keith Thompson
Keith Thompson

Reputation: 263267

[ is actually a command (it happens to be built into most shells), not just part of the syntax of an if statement.

The if statement executes the command that is its argument. If that command succeeds (sets $? to zero), then the condition is true; if it fails (sets $? to some non-zero value), the condition is false.

The built-in [ command is almost exactly equivalent to the test command; the difference is that [ requires ] as its last argument.

See also https://unix.stackexchange.com/a/22728/10454

Upvotes: 4

Related Questions