-1

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
AKozak
  • 85
  • 5

3 Answers3

3

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).

larsks
  • 277,717
  • 41
  • 399
  • 399
  • I'm sorry if you had a problem with this answer. If you feel it didn't adequately address your question you are welcome to accept another one. Pretty sure I'm right, though. – larsks Aug 22 '19 at 03:06
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
joanis
  • 10,635
  • 14
  • 30
  • 40
0

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
chepner
  • 497,756
  • 71
  • 530
  • 681