0

I am just trying to get something straight as to why the following returns false:

echo $[ $(( 2100%4 )) == 0 ] --> returns '1'

I know I am probably missing something simple.

SecretAgentMan
  • 2,856
  • 7
  • 21
  • 41
mvoight
  • 11
  • 3
  • 1
    @Carcigenicate : Shell scripting has a different meaning for truth and false, so `0` indicates "no problem" (i.e.success, true), while any non-zero number is available to report a particular documented error, i.e. file not found, can't access file, etc although may programs just return `1` (false) for any/all errors. Read the man page for the particular cmd you are checking. You can see this for yourself by typing `true` and the immediately `echo $?` is the return status of the most recently executed cmd and `false ; echo $?` will return `1`. Good luck to all. – shellter Jan 16 '20 at 23:52
  • @shellter : I thought the same, do you think you could possibly explain as to why the expression I am testing is returning false then? – mvoight Jan 16 '20 at 23:53
  • It's my recollection that the form `$[ LHSexpr test RHSexpr]` (using the leading `$`) is an ancient form.So I can't speak for that. POSIX tests are done like `if [ LHSexpr test RHSexpr]`, and `bash/ksh/zsh` offer an advanced test with `if [[ .... ]] ; ..` which allows even more advanced testing. Sorry can't get an URL for you now. Hm .. just noticed you're using `$(( math ))` which indicates you're using a feature rich shell. If you are using the leading `echo` to debug, I would remove that and uset `set -vx` to see the levels of evaluation inside your code. Good luck. – shellter Jan 17 '20 at 00:01
  • As you are using a shell with `$((...))`. then I'd recommend rewriting your test like `if (( 2100%4 == 0 )) ; then echo returned $? ; else echo else returned $? ;`. Note that `if (( 2100%8 == 0 )) ; then echo returned $? ; else echo else returned $? ; fi` returns the `else` error message (as it should). Good luck. – shellter Jan 17 '20 at 00:12
  • 1
    https://stackoverflow.com/questions/669452/is-double-square-brackets-preferable-over-single-square-brackets-in-ba/669486?r=SearchResults&s=3|55.4521#669486 will probably have all the detail you need. Good luck. – shellter Jan 17 '20 at 00:15
  • `$[...]` is an old form of `$((...))` and the arithmetic expression `0 == 0` is evaluated to be `1` as other languages. – tshiono Jan 17 '20 at 00:28

1 Answers1

2

In short "meaning" differs from "value".

A zero exit status means success. A nonzero exit status means failure.

A zero value is associated with "false" boolean state. A nonzero value is associated with "true" boolean state.

The [ ... ] is the same as test .... The test command exits with a nonzero exit status if the expression inside is false (as in really false, not true). The test command exits with a zero exit status if the expression inside is true.

The $[ ... ] is an old, undocumented and deprecated form of $(( ... )) arithmetic expansion (there's also the expr ... that you should not use).

The if expr; then body; fi executes the body part only if expr exits with a zero exit status, ie. meaning "success" here.

So:

echo $[ $(( 2100%4 )) == 0 ] 

will print 1. The $(( 2100%4 )) will do the arithmetic operation and expand to 0. The arithmetic expansion work as in C language. The result of == arithmetic operation is 1 if the numbers are equal, it's 0 if the numbers are not equal. The $[ 0 == 0 ] will do the arithmetic operation and expand to just a number 1, as this will be the result of == operator.

While the:

[ $(( 2100%4 )) == 0 ] 

Executes the [ 0 == 0 ], it's same as test 0 == 0. Because the expression 0 == 0 evaluated by test command is true, so test command exits with 0 exit status, which means "success". Note that == is a bash extension for = and it does string comparison, it compares 0 to 0 lexicographically. It does not compare numbers and it differs from arithmetic operator.

There is also bash extension (( ... )) syntax. The (( ... )) evaluates the arithmetic expression and if the result of arithmetic is equal to "true" boolean state (ie. it result in a nonzero value), then the (( .. )) exits with a zero exit status (meaning success). If the expression evaluates to 0, ie. "false" boolean state, then the (( ... )) exits with a nonzero exit status. Note the difference.

So you can:

if (( 2100%4 == 0 )); then something; fi

The 2100%4 == 0 is equal to 1, which is "true" boolean state, which means (( exits with a zero exit status, which means success, which means the body of the if will execute.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • Thanks for clarifying my comments. I don't think I ever understood before why "`2100%4 == 0` is equal to `1`", but your explanation makes it clear. Thanks! – shellter Jan 17 '20 at 01:02