Search code examples
bashshzsh

Shell string vs. integer comparison


I have found that if I have

time='9'

then

[ "$time" = 9 ]
[ "$time" = '9' ]
[ "$time" -eq 9 ]
[ "$time" -eq '9' ]

all eval true. This is unusual, since I am used to quotations depicting strings and no quotes being integers, and I had thought -eq is integer comparison and = is string. What is the explanation here?

I check this on zsh.


Solution

  • Shell syntax works very differently from what you're used to. In the shell, pretty much everything is fundamentally a string; but if you use it in a context where a number is needed, the shell will try to parse that string into a number and use that (and then if there's a numeric result, it'll convert the result into a string for storage/display/whatever).

    In the case of a [ = ] test, the strings are just compared directly. In [ -eq ], they're converted to numbers and the numbers are compared. So, for example, [ 05 = 5 ] is false because "05" is not the same string as "5", but [ "05" -eq "5" ] is true because "05" and "5" both parse out to the same number.

    Quoting doesn't affect this. What quoting does is change how the characters within the quoted section are parsed. The important thing with double-quoting variables is that it prevents the variable's value from being split into multiple words and/or wildcard-expanded into a list of matching filenames, both of which can cause chaos. zsh doesn't do this by default, so it's (usually) safe to leave the double-quotes off. But IMO double-quoting is still a good habit, since you won't necessarily always be in zsh.