Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Out of curiosity, when doing a bash variable comparison (its value being an integer) it's possible to test it against some predefined value either declared as an int or as a string.

Sample script:

#!/bin/bash
f1()
{
        [ "$1" == "1" ] && echo "$FUNCNAME: \"1\" compared as string"
}

f2()
{
        [[ "$1" -eq 1 ]] && echo "$FUNCNAME: \"1\" compared as int"
}

f1 $1
f2 $1

Output:

$  ./param.sh 1
f1: "1" compared as string
f2: "1" compared as int

and

$  ./param.sh blah
$

Both functions behave the same way, and so I'm wondering if there's a preferred way when checking an integer variable? I would go for checking int versus int as it's more strict but I wonder if there are any draw backs doing it with string?

In this case, f2() is also more strict about the comparison, i.e. passing a decimal value will break it, whereas f1() will take it no problem.

share|improve this question
    
Note that Bash doesn't really has an Integer datatype. You can basically just hint Bash to treat a String as an integer. –  helpermethod Jul 11 at 9:04

3 Answers 3

up vote 9 down vote accepted

Yep, lots of differences. For instance, = checks for exact string equality, but -eq evaluates both expressions arithmetically before checking for equality:

$ [ " 1 " -eq 1 ] && echo equal || echo not
equal
$ [ " 1 " = 1 ] && echo equal || echo not
not

$ [ +1 -eq 1 ] && echo equal || echo not
equal
$ [ +1 = 1 ] && echo equal || echo not
not

$ [ "0+1" -eq 1 ] && echo equal || echo not
equal
$ [ "0+1" = 1 ] && echo equal || echo not
not

Also, the empty string happens to be numerically equal to zero:

$ [ "" -eq 0 ] && echo equal || echo not
equal
$ [ "" = 0 ] && echo equal || echo not
not

And a whole other class of differences appears when you bring the comparison operators in - considering < vs -lt, for instance:

$ [[ 2 -lt 10 ]] && echo less || echo not
less
$ [[ 2 < 10 ]] && echo less || echo not
not

This is because the string "2" is alphabetically after the string "10" (since 1 comes before 2), but the number "2" is numerically less than the number "10".

share|improve this answer
1  
+1 The equal sign (=) sometimes checks for exact string equality (when used as a comparison operator), and other times it is functioning as an assignment operator. tldp.org/LDP/abs/html/comparison-ops.html#EQUALSIGNREF –  Christopher Jul 10 at 16:21
2  
Don't forget there's also (( ... )) for numeric operations. (( " 1 " == 1 )) && echo yes || echo no results in yes –  Patrick Jul 10 at 16:51

Integer vs. string comparison becomes most significant when you are comparing greater or lesser than:

#!/bin/bash

eleven=11
nine=9

[[ $nine < $eleven ]] && echo string   # fail

[[ "$nine" -lt "$eleven" ]] && echo integer # pass

The first one fails because 9 comes after 11 when sorted lexicographically.

Note that using quotes does not determine whether you are comparing strings or numbers, the operator does. You can add or remove the quotes above, it does not make any difference. Bash catches undefined variables within double brackets, so quotes are not necessary. Using quotes with single brackets for numerical tests won't save you since:

[ "" -lt 11 ]

is an error anyway ("integer expression required"). Quotes are an effective safeguard with string comparisons in single brackets:

[ "" \< 11 ]

Note within double brackets, "" will -eq 0 but not == 0.

share|improve this answer
1  
In bash, it's not strictly necessary to quote variables within double brackets: the builtin [[ is smart enough to remember where the variables are, and it won't get fooled by empty variables. Single brackets ([) do not have this feature, and require quotes. –  glenn jackman Jul 10 at 15:28
    
@glennjackman Had not noticed that. [[ -lt 11 ]] is an error, but nothing=; [[ $nothing -lt 11 ]] is not. I've reworked the last paragraph a bit. –  goldilocks Jul 10 at 15:48

In addition to what has been said.
Comparing for equality is faster with numbers, although in shell scripting it is rare that you need fast calculation.

$ b=234
$ time for ((a=1;a<1000000;a++)); do [[ $b = "234" ]]; done

real    0m13.008s
user    0m12.677s
sys 0m0.312s

$ time for ((a=1;a<1000000;a++)); do [[ $b -eq 234 ]]; done

real    0m10.266s
user    0m9.657s
sys 0m0.572s
share|improve this answer
    
Considering that they do different things, I'd say the performance is irrelevant - you need to use the one that does what you want. –  godlygeek Jul 10 at 15:28
    
@godlygeek Equality comparison of a variable can be achieved both way. "-eq" is faster. –  Emmanuel Jul 10 at 15:33
    
They test for different definitions of equality. If you want to answer the question "Does this variable hold the exact string 123", you can only use =, since using -eq would match for "+123" as well. If you wanted to know "Does this variable, when evaluated as an arithmetic expression, compare equal to 123", you could only use -eq. The only time I can see where a programmer wouldn't care which definition of equality was used is when he knows that the contents of the variable are constrained to a particular pattern ahead of time. –  godlygeek Jul 10 at 16:16
    
@godlygeek interesting, the question was about comparing equality of numbers as if they were strings, does it fits the case of variables constrained ahead of time to a particular pattern ? –  Emmanuel Jul 10 at 16:29
    
Your example (b=234) fits that pattern - you know it's not +234 or " 234 " or "233+1", since you assigned it yourself, so you know that it comparing it as a string and as a number are equally valid. But the OP's script, since it takes input as a command line argument, doesn't have that constraint - consider calling it as ./param.sh 0+1 or ./param.sh " 1" –  godlygeek Jul 10 at 16:35

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.