What is the difference between the following commands and why do they not produce the same output?:
echo $[ "a" == "a" ]
1
echo $(( "a" == "a" ))
1
[ "a" == "a" ]; echo $?;
0
What is the difference between the following commands and why do they not produce the same output?:
echo $[ "a" == "a" ]
1
echo $(( "a" == "a" ))
1
[ "a" == "a" ]; echo $?;
0
To me, these seem like the same operations but the first two which are appended with $ return false...
That's incorrect. The first two expressions are arithmetic expressions. They produce a numeric result. As is common in many languages, a boolean True evaluates as the integer value 1
, and False evaluates as 0
.
Note that $[...]
and $((...))
are equivalent, but the former is deprecated and is no longer documented.
...while the third returns true
This isn't true either. Here you are looking at the return code of a command, rather than printing out the value of an expression as you are doing in the first two examples. Commands don't return boolean information; they return an integer indicating whether they were successful (a return code of 0) or not (any non-zero return code).
Regarding your question, the false
command doesn't return "false"; if you read the man page, it says:
false - do nothing, unsuccessfully
That is, it is a command that does nothing and returns an error code (i.e., a nonzero exit code, in this case, 1
). true
is similar, of course, except it returns a successful exit code (i.e., 0
).
echo $[ "a" == "a" ]
uses the deprecated integer expansion syntax, which has been replaced by $(( ... ))
.
echo $(( "a" == "a" ))
uses what is called arithmetic expansion: inside $(( ... ))
, you can have logical and numerical expressions that get calculated before returning the value.
[ "a" == "a" ]; echo $?
does a logical test in standard bash fashion: the return code of a program is 0 when that program executes successfully, and non-zero otherwise. [
is actually another name for the program called test
, which returns success (i.e., 0) when the expression it tests is true.
Not in your list, but related:
(( "a" == "a" )); echo $?
0
this does arithmetic expansion, and returns success (0) if the result is true, rather than producing the value of the expression itself.
[[ "a" == "a" ]]; echo $?
0
[[ ... ]]
is bash syntax for doing conditional tests directly instead of calling the program test
.
Some sample usages
You would use $(( ... ))
to initialize variables or echo output, as you did:
foo=$(( 1 + 4))
echo $(( 5 + 7 ))
You would use [ ... ]
, (( ... ))
and [[ ... ]]
in conditional statements:
if [[ $a == bar ]]; then
echo $a is bar
fi
i=0
while (( i < 10 )); do
echo i=$i
i=$(( i + 1 ))
done
Your first two perform arithmetic comparisons (never use $[...]
; it's undocumented, obsolete, and was replaced by $((...))
—literally—decades ago). In an arithmetic context, strings are treated as implicit parameter expansions, recursively, until an integer is produces. Undefined parameters are treated as 0. The resulting expression has value 1 if the comparison is true, 0 if false. Compare:
$ echo $(( a == b )) # Compares 0 == 0
1
$ a=5; b=7
$ echo $(( a == b )) # Compares 5 == 7
0
The last one performs string comparison, as expected. The exit status of [ ... ]
is 0 when the comparison is true, 1 when false. (This is the difference between the value of a Boolean expression, and the result of a command that evaluates a Boolean expression.) Integer comparisons are made using the -eq
operator.
$ [ a = a ]; echo $? # String comparison of the letter a to itself
0
$ [ a = b ]; echo $? # String comparison of the letter a to the letter b
1
$ unset a b
$ [ a -eq b ]; echo $? # Again, 0 -eq 0
0
$ a=5; b=7
$ [ "$a" -eq "$b" ]; echo $? # Again, 5 -eq 7
1