Bash – what are the differences between `==` and `=` in conditional expressions

bash

From bash manual, for conditional expressions

string1 == string2
string1 = string2

True if the strings are equal.

  1. When used with the [[ command, this performs pattern matching as described above (see Section 3.2.4.2 [Conditional Constructs], page
    10).

    • What does "pattern matching" mean here?

    • What is "pattern matching" opposed to here?

    • If not used with [[ but with other commands, what does "this" perform?

  2. ‘=’ should be used with the test command for posix conformance.

    • What does POSIX say here?

    • What is the sentence opposed to?

    • Can == be used with test command? I tried and it seems yes.

    • Can = be used with other commands besides test? I tried = with [[ and [, and it seems yes.

  3. what are the differences between == and =?

    In Bash 4.3, I tried == and = with test, [[, and [. ==
    and = look the same to me.

    Can == and = be used interchangeably in any conditional expression?

Thanks.

Best Answer

POSIX test (or [ ... ]) only knows about the one with a single equal sign:

s1 = s2
True if the strings s1 and s2 are identical; otherwise, false.

But Bash accepts the double equal sign too, though the builtin help doesn't admit to that (the manual does):

$ help test | grep =  -A1
  STRING1 = STRING2
                 True if the strings are equal.
  STRING1 != STRING2
                 True if the strings are not equal.

As for other shells, it depends. Well, particularly Dash is the stubborn one here:

$ dash -c '[ x == x ] && echo foo'
dash: 1: [: x: unexpected operator

but

$ yash -c '[ x == x ] && echo foo'
foo
$ busybox sh -c '[ x == x ] && echo foo'
foo
$ ksh93 -c '[ x == x ] && echo foo'
foo

zsh is a bit odd here, == is considered a special operator, so it must be quoted:

$ zsh -c '[ x == x ] && echo foo'
zsh:1: = not found

$ zsh -c '[ x "==" x ] && echo foo'
foo

The external test/[ utility from GNU coreutils on my Debian supports == (but the manual doesn't admit that), the one on OS X doesn't.

So, with test/[ .. ], use = as it's more widely supported.


With the [[ ... ]] construct, both = and == are equal (at least in Bash) and the right side of the operator is taken as a pattern, like in a filename glob, unless it is quoted. (Filenames are not expanded within [[ ... ]])

$ bash -c '[[ xxx == x* ]] && echo foo'
foo

But of course that construct isn't standard:

$ dash -c '[[ xxx == x* ]] && echo foo'
dash: 1: [[: not found
$ yash -c '[[ xx == x* ]] && echo foo'
yash: no such command ‘[[’

And while Busybox has it, it does't do the pattern match:

$ busybox sh -c '[[ xx == xx ]] && echo yes || echo no'
yes
$ busybox sh -c '[[ xx == x* ]] && echo yes || echo no'
no