7

I'm learning the basics of shell programming, so I wrote something simple like

#!/bin/bash read var1 read var2 if [ var1 -lt var2 ]; then echo "var1 is lt var2" else echo "var2 is lt var1" fi 

My understanding is that variables are untyped in Bash, and that any variable may be used as an integer if it only contains digits. But I get the error "integer expression expected" when I run this... why?

    2 Answers 2

    10

    Actually you can set some attributes on variables using the declare (or the old typeset) builtin. declare -i var1 var2 will set integer attribute on those variables. After that assignments which attempt to set non-integer values to those variables will raise error.

    But your problem is with the syntax. When using a variable's value you have to prefix its name with $:

    if [ "$var1" -lt "$var2" ]; then echo "$var1 is lt $var2" else echo "$var2 is lt $var1" fi 

    Exceptions are the arithmetic evaluations, where is no need for the $:

    if ((var1<var2)); then echo "$var1 is lt $var2" else echo "$var2 is lt $var1" fi 

    As a word of warning, inside [..] always double quote your variables to avoid word expansion messing up your expression's syntax. (I mean, you will have problems with unset variables, variables containing empty string and variables containing IFS characters.) Or you can use the newer and better [[..]] instead which handles such cases correctly:

    if [[ $var1 -lt $var2 ]]; then echo "$var1 is lt $var2" else echo "$var2 is lt $var1" fi 
    2
    • Also, [[ $var1 < $var2 ]] is a string comparison, not an arithmetic comparison... [[ 11 > 2 ]] tests as false ... [[ 11 -gt 2 ]] tests as true
      – Peter.O
      CommentedJul 13, 2012 at 17:24
    • @Peter.O, you are right. Since I use only arithmetic evaluation for numeric comparisons, I forgot that. Thank you.
      – manatwork
      CommentedJul 13, 2012 at 17:27
    2

    You should reference variables prepending the name with $

    if [ $var1 -lt $var2 ] ; then... 
    1
    • And you should quote those variables "$var1" -lt "$var2" unless you have a very good reason for not doing so.CommentedNov 10, 2016 at 9:43

    You must log in to answer this question.