I am a bit struggling with bash programming, because I don't seem to understand the syntax rules. For example:
read confirm
if [ "$confirm" == "yes" ]; then
echo "Thank you for saying yes"
else
echo "Why did you say no?"
fi
In this code, you can use many forms to do the same thing:
"$confirm" == "yes"
$confirm == "yes"
"$confirm" == yes
$confirm == yes
So what is the rule? Besides that, it is very strict, so if you write the above if statement without the space between '[' and '"', you would get an error. So my questions:
Regards,
Rafid
The rules are simple but subtle. The examples you gave are not all equivalent, they have subtly different meanings. For a fairly good reference you can read Shell Command Language, which covers POSIX shells. Most shells, certainly including bash, zsh and ksh, are POSIX shells and will implement at least what is listed there. Some shells may conform to earlier versions of the specification or be similar but not conformant.
The primary rule that you will need to remember if you are learning Unix shell scripting is this: Expressions are separated by spaces. Technically they are separated by whatever characters are listed in the variable $IFS, but this amounts to whitespace under normal circumstances.
If you say ["$a"="$b"]
in bash the shell tries to read the entire string as a command, evaluating $a and $b in place. Supposing the value of $a
was a literal a
and the value of $b
was a literal b
, the shell would attempt to execute a command called [a=b]
, which is a legal file name. The quotation marks were interpreted by the shell as special but the [
was not, because it is only special if written as a separate token. It was not separated by spaces.
Almost everything you see and do in a shell is a command. The character [
isn't syntax, it's a command. Commands take arguments, separated by spaces. What those arguments mean is up to the command, not the shell. In C if ( a == b )
is handled all by the parser, except for the values of a and b. In bash if [ "$a" == "$b" ]
is first parsed by the shell, which evaluates the variables $a and $b, and then the command [
is executed. Sometimes this is a shell builtin command, sometimes it is literally a separate executable (look for /bin/[
in your system). This means that a == b ]
is not interpreted by bash at all but instead is a kind of domain-specific language that is interpreted by [
, which is also known as test
. In fact you can write if test "$a" == "$b"
instead. In this form test
does not require the closing ]
, but everything else is the same. To see what test
will do with these arguments read help test
or man test
.
The other rule to remember when learning Unix shell scripting is this: Variables are expanded first, commands are evaluated second. This means that if you have a space in a variable, such as foo="a b"
then the shell will see the space after the variable is expanded: ls $foo
by itself will complain that it cannot find the file a
and it cannot find the file b
. To get the behavior you probably expect from other languages you almost always will want to quote your variables: ls "$foo"
, which instructs the shell that the expanded variable is to be treated as a single string and not re-tokenized.
Shell scripting is filled with oddities but it is not irrational (at least not most of the time). Some historical warts do exist but there are really not very many rules to remember once you get the hand of the basics. Just do not expect it to operate like a conventional C-like language and you won't be too surprised.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With