The rules are simple but subtle. The examples you provided are not all equivalent, they have subtly different meanings. For a good reference, you can read the Shell Command Language , which covers POSIX shells. Most shells, including bash, zsh, and ksh, are POSIX shells and will implement at least what is specified there. Some shells may comply with earlier versions of the specification or may be similar but not consistent.
The basic rule that you need to remember if you are studying a Unix shell script is this: expressions are separated by spaces. Technically, they are separated by any characters listed in the $ IFS variable, but under normal conditions this means a space.
If you say ["$a"="$b"] in bash, the shell tries to read the entire line as a command, evaluating $ a and $ b in place. Suppose that the value of $a was literal a , and the value of $b was literal b , the shell tried to execute a command called [a=b] , which is the legal name of the file. The quotes were interpreted by the shell as special, but [ were not, because they are only special if they are written as a separate token. It was not separated by spaces.
Almost everything you see and do in the shell is a team. The character [ not syntax, it is a command. Commands accept arguments separated by spaces. What these arguments mean depends on the team, not the shell. In C, if ( a == b ) processed by the parser, except for the values of a and b. In bash, if [ "$a" == "$b" ] first parsed by the shell, which evaluates the variables $ a and $ b, and then the [ . Sometimes it is a command shell, sometimes it is literally a separate executable file (look for /bin/[ on your system). This means that a == b ] is not interpreted by bash at all, but instead is a kind of domain language that is interpreted by [ , which is also known as test . In fact, you can write if test "$a" == "$b" . In this form test , closing is not required ] , but everything else is the same. To see what test will do with these arguments, read help test or man test .
Another rule to keep in mind when exploring Unix shell scripts: Variables expand first, commands are evaluated secondly. This means that if you have a space in the variable, for example foo="ab" , then the shell will see a space after the variable expansion: ls $foo will complain by itself that it cannot find file a and it cannot find file b . To get the behavior that you probably expect from other languages, you will almost always want to quote your variables: ls "$foo" , which instructs the shell that the extended variable should be treated as a single line and not re-marked.
The shell script is filled with oddities, but it is not irrational (at least not in most cases). Some historical warts really exist, but there really aren't very many rules to remember as soon as you get your hand off the basics. Just don’t expect it to work like a normal C-like language and you won’t be too surprised.