1

I have some bash issues:

This is expected:

[[ 0 -eq 0 ]] && echo "equal!"
> equal!

This is not:

[[ "" -eq 0 ]] && echo "equal!"
> equal!

Why is "" equal to 0?

How can I check for numeric equality?

Marko Previsic
  • 1,820
  • 16
  • 30
volingas
  • 1,023
  • 9
  • 21
  • 1
    This might help: [How do I test if a variable is a number in Bash?](https://stackoverflow.com/q/806906/3776858) – Cyrus Jun 14 '19 at 15:57
  • 2
    If you're only checking for equality and are not sure your variable is numeric, then I suggest you use string comparison instead, e.g. `[[ "" == 0 ]]`. If you want numeric equality then you can use `[ "" -eq 0 ]` or `(( "" == 0 ))` but those will display an error message on stderr telling you they expect an integer (or are missing an operand) – Aaron Jun 14 '19 at 16:04
  • Possible duplicate of [Bash Equality Operators ( == , -eq )](https://stackoverflow.com/questions/20449543/bash-equality-operators-eq) – jeremysprofile Jun 14 '19 at 16:53
  • 1
    The empty string get's converted to `0`. Ie. `[[ "" -eq 1 ]]` is false. – KamilCuk Jun 14 '19 at 17:10
  • `if [[ "$(who am i)" == "$(who am not)" ]]; then echo "what?"; fi` gives, the following output: `what?` Once you know why, then you'll find BASH scripting is actually very easy. – AKS Jun 14 '19 at 17:34

1 Answers1

-1

This is because Bash tries hard to convert whatever you put into both sides of -eq into integers, and will convert the empty string to zero. The conversions are far from trivial. Here's how I expect the code parses numbers, without actually having read it:

$ [[ x -eq 0 ]] && echo "equal!"
equal!

After Bash detects a numeric context (-eq) it starts creating a number from zero on the left side, scans and finds x, discards it, scans and finds whitespace, and therefore considers the left side zero. Hence the above is equivalent to [[ 0 -eq 0 ]]

$ [[ 0x10 -eq 16 ]] && echo "equal!"
equal!

Starting from zero again, Bash sees a zero (before the "x") and goes into "alternate base" mode, finds an "x" and goes into hexadecimal mode, and reads the remaining digits ("10") as a hexadecimal number.

$ [[ 00x10 -eq 16 ]] && echo "equal!"
bash: [[: 00x10: value too great for base (error token is "00x10")

After going into "alternate base" mode after seeing a zero Bash sees a number (the second zero), and therefore goes into octal mode. x is considered a "numeric character" in this mode because it can be used in higher bases, but "x" is not a valid octal digit, so it fails.

See the Bash manual for more.

l0b0
  • 55,365
  • 30
  • 138
  • 223
  • Re: "Bash starts with a zero on the left side, scans and finds x, discards it, scans and finds whitespace, and therefore considers the left side zero": If you mean to say that `[[ x -eq 0 ]]` is equivalent to `[[ -eq 0 ]]`, then -- no, that's not true. Rather, `[[ x -eq 0 ]]` is equivalent to `[[ $((x)) -eq 0 ]]`, and therefore roughly equivalent to `[[ "$x" -eq 0 ]]`: it interprets `x` as an arithmetic expression, which involves taking the *parameter* `x` and interpreting its *value* as an arithmetic expression. – ruakh Jun 15 '19 at 07:39
  • 1
    I'm the downvoter. I downvoted because of what I pointed out in my previous comment. (I didn't downvote *immediately*, because I waited to see if you would reply either in a way that made it make sense or in a way that acknowledged the error. Instead, you replied in a way that doubled-down on an explanation that doesn't make sense and is clearly wrong in light of `x=1 ; [[ x -eq 1 ]] && echo "equal!"`. Since you don't want to fix the issue, I decided it best to simply downvote so as to alert unwary readers.) – ruakh Jun 15 '19 at 17:15