1

What's the difference between these:

SEC=$(mysql -hxxx -Pxxx -uxxx -pxxx -se "SELECT Seconds FROM tablename")

SEC=100

Both return the same result (100). But when I test it with:

if [ ${SEC} > 1 ]
then
    echo "SEC GT 1"
else
    echo "SEC LT 1"
fi

The first one returns:

"SEC GT 1"

The second one returns:

"SEC LT 1"

If however, I change it to:

if [ ${SEC} -gt 1 ]

then the result is reversed.

I'm assuming it's got something to do with the datatype, and that I presumbaly need to cast one or the other to get the same result.

It's just that at present it's messing up my testing, as I have to remember to change the IF section every time.

5
  • 2
    > is string comparison and the -gt is arithmetic.
    – 123
    Commented Feb 15, 2016 at 11:53
  • 9
    if [ ${SEC} > 1 ] > is the file redirection operator in this context. Are you finding a file named "1" after your run this script?
    – Kenster
    Commented Feb 15, 2016 at 12:13
  • > is not valid operator for the [ command; you be thinking of bash's [[.
    – Jeff Schaller
    Commented Feb 15, 2016 at 12:15
  • 5
    @JeffSchaller, while > is not a standard [/test operator, many implementations support it (some as a byte-array comparison operator ([ builtin of bash, dash or mksh), some as a string comparison operator ([ builtin of AT&T ksh or yash)). Of course, it needs to be quoted for the shell not to treat it as the redirection operator. Commented Feb 15, 2016 at 12:24
  • Related unix.stackexchange.com/a/222656/38906
    – cuonglm
    Commented Feb 15, 2016 at 16:34

1 Answer 1

6

Originally, [ was implemented as an ordinary command, identical to test except that [ expects an extra argument at the end which must be ]. (It still exists as an ordinary command, but most shells also have those as built-ins.) Given that it's an ordinary command subject to ordinary parsing, it couldn't use mathematical operators < and > without quoting: [ ${SEC} > 1 ] contains a redirection operator, it's equivalent to [ ${SEC} ] >1, redirecting the (empty) output of the [ command to the file called 1. The [ command mostly follows the usual convention of making special options beginning with a dash: most of its operators begin with a dash. So there's [ -r foo ] to test whether a file is readable, [ -r foo -a -w bar ] to combine two tests with the “and” operator, [ $x -eq $y ] to test whether $x and $y are equal, etc.

These older shells had string equality (the = operator, one of the few that deviates from the dash-letter convention) but not string ordering¹. They had numerical comparisons though, e.g. [ $x -le $y ] to test whether the integer $x is smaller or equal to $y, and this set of operators includes numerical equality [ $x -eq $y ] where [ 010 -eq 8 ] because a leading zero means that the number is in octal.

Ksh introduced the syntax [[ … ]], also available now in bash and zsh. Unlike [ … ], which is an ordinary command, [[ … ]] is recognized by the shell's parser, and so special characters such as ( and < can be used inside without quoting (and indeed they must not be quoted). Since -lt and friends were already available for numerical comparisons, and = was already doing a string comparison, < and friends were made string comparison operators (lexicographic order¹). Thus, for example, [ 9 -lt 10 ] but [[ 10 < 9 ]].

¹ String ordering is available with the expr utility; it's one of the few uses of expr that haven't been subsumed by features of POSIX shells. But beware that expr uses the same operator for string and numerical comparisons, so expr 9 \< 10 but expr a9 \> a10.
² Whether the strings are interpreted as byte strings, or as character strings in the current locale, depends on the shell

1
  • cheers, that's a great explanation, and very helpful.
    – IGGt
    Commented Feb 16, 2016 at 8:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .