User Tools

Site Tools


2018numeric_cmp

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
2018numeric_cmp [2018/09/07 10:59]
david
2018numeric_cmp [2018/09/07 14:02] (current)
david [Incorrect Numeric Comparisons (lexicographic order)]
Line 1: Line 1:
-====== ​Confusing comparison ​operators in BASH ======+~~NOTOC~~ 
 +====== ​Comparison ​operators in BASH ====== 
 + 
 +The multiple constructs that are available in BASH can lead to confusion.  
 + 
 +===== Brackets ===== 
 +  * Single brackets <​nowiki>​[ ]</​nowiki>​ are generally OK, but might allow some syntax to be interpreted as commands (thus causing errors) 
 +  * Double brackets <​nowiki>​[[ ]]</​nowiki>​ have less parsing, so are generally safer to use. 
 + 
 +===== Correct Numeric Comparisons ===== 
 +You must use the flag operators, or the symbolic operators inside double parentheses,​ to correctly compare values numerically. 
 +For example, say ''​a=2''​ and ''​b=10'':​  
 +  * <​nowiki>​[ 2 -lt 10 ]</​nowiki>​ is TRUE 
 +  * <​nowiki>​[[ 2 -lt 10 ]]</​nowiki>​ is TRUE 
 +  * <​nowiki>​[[ 2 -ge 10 ]]</​nowiki>​ is FALSE 
 +  * <​nowiki>​(( 2 < 10 ))</​nowiki>​ is TRUE 
 + 
 +===== Incorrect Numeric Comparisons (lexicographic order) ===== 
 +What results in an alphanumeric comparison (which has unexpected behavior), or a syntax error (which you may overlook) is the following:​ 
 +  * <​nowiki>​[[ 2 < 10 ]]</​nowiki>,​ alphanumerically FALSE 
 +  * <​nowiki>​[ 2 < 10 ]</​nowiki>,​ error; also FALSE. 
 + 
 +===== Importance of Testing ===== 
 + 
 +Whenever I have a question about a confusing syntax issue, I write a short test script to flesh out all the possibilities. To distinguish between the correct, incorrect, and error-producing constructs, I wrote a script that produces this table:
  
 ^ Syntax ^ Output ^  Error  ^ ^ Syntax ^ Output ^  Error  ^
-| Numeric comparisons: ​**2 less than 10** should be **TRUE** ||| +||| 
-|                                                    ​|||+Numeric comparisons: ​__2 less than 10__ should be __TRUE__ ​|||
 | ''<​nowiki>​[ 2 < 10 ]</​nowiki>'' ​     | FALSE | ''<​nowiki>​10:​ No such file or directory</​nowiki>''​ | | ''<​nowiki>​[ 2 < 10 ]</​nowiki>'' ​     | FALSE | ''<​nowiki>​10:​ No such file or directory</​nowiki>''​ |
 | ''<​nowiki>​[ 2 \< 10 ]</​nowiki>'' ​    | FALSE | | | ''<​nowiki>​[ 2 \< 10 ]</​nowiki>'' ​    | FALSE | |
Line 13: Line 37:
 | ''<​nowiki>​(( 2 < 10 ))</​nowiki>'' ​   | TRUE  | | | ''<​nowiki>​(( 2 < 10 ))</​nowiki>'' ​   | TRUE  | |
 | ''<​nowiki>​(( 2 -lt 10 ))</​nowiki>'' ​ | FALSE |''<​nowiki>​((:​ 2 -lt 10 : syntax error (error token is "10 "​)</​nowiki>''​ | | ''<​nowiki>​(( 2 -lt 10 ))</​nowiki>'' ​ | FALSE |''<​nowiki>​((:​ 2 -lt 10 : syntax error (error token is "10 "​)</​nowiki>''​ |
 +| |||
 +^ Numeric comparisons:​ __10 less than 2__ should be __FALSE__ |||
 +| ''<​nowiki>​[ 10 < 2 ]</​nowiki>''​ |  FALSE | ''<​nowiki>​2:​ No such file or directory</​nowiki>''​ |
 +| ''<​nowiki>​[ 10 \< 2 ]</​nowiki>''​ | TRUE ​ | |
 +| ''<​nowiki>​[[ 10 < 2 ]]</​nowiki>''​ | TRUE ​ | |
 +| ''<​nowiki>​[[ 10 -lt 2 ]]</​nowiki>''​ | FALSE | |
 +| ''<​nowiki>​[ 10 -lt 2 ]</​nowiki>''​ | FALSE | |
 +| ''<​nowiki>​test 10 -lt 2</​nowiki>''​ | FALSE | |
 +| ''<​nowiki>​(( 10 < 2 ))</​nowiki>''​ | FALSE | |
 +| ''<​nowiki>​(( 10 -lt 2 ))</​nowiki>''​ | FALSE | ''<​nowiki>​((:​ 10 -lt 2 : syntax error (error token is "2 "​)</​nowiki>''​ |
 +
 +This script is:
 +
 +<code bash>
 +#​!/​usr/​bin/​env bash
 +# numeric_comparisons.bash - 
 +# Distinguish valid numeric versus ​
 +# lexicographic comparison constructs.
 +###
 +
 +a=2
 +b=10
 +echo "​Numeric comparisons:​ $a less than $b should be TRUE"
 +echo "​------------------------------------"​
 +echo -ne "[ $a < $b ]\t"
 +[ $a < $b ] && echo "​TRUE"​ || echo "​FALSE"​
 +
 +echo -ne "[ ! $a -lt $b ]\t"
 +[ ! $a -lt $b ] && echo "​TRUE"​ || echo "​FALSE"​
 +
 +echo -ne "[ $a \< $b ]\t"
 +[ $a \< $b ] && echo "​TRUE"​ || echo "​FALSE"​
 +
 +echo -ne "[[ $a < $b ]]\t"
 +[[ $a < $b ]]  && echo "​TRUE"​ || echo "​FALSE"​
 +
 +echo -ne "[[ $a -lt $b ]]\t"
 +[[ $a -lt $b ]]  && echo "​TRUE"​ || echo "​FALSE"​
 +
 +echo -ne "[ $a -lt $b ]\t"
 +[ $a -lt $b ] && echo "​TRUE"​ || echo "​FALSE"​
 +
 +echo -ne "[ \"​$a\"​ -lt \"​$b\"​ ]\t"
 +[ "​$a"​ -lt "​$b"​ ] && echo "​TRUE"​ || echo "​FALSE"​
 +
 +echo -ne "test $a -lt $b\t"
 +test $a -lt $b  && echo "​TRUE"​ || echo "​FALSE"​
 +
 +echo -ne "(( $a < $b ))\t"
 +(( $a < $b ))  && echo "​TRUE"​ || echo "​FALSE"​
 +
 +echo -ne "(( $a -lt $b ))\t"
 +(( $a -lt $b ))  && echo "​TRUE"​ || echo "​FALSE"​
 +
 +# Reverse the values of a and b. 
 +# This should reverse the outcomes
 +# of the above commands.
 +a=10
 +b=2
 +echo "​Numeric comparisons:​ $a less than $b should be FALSE"
 +echo "​------------------------------------"​
 +echo -ne "[ $a < $b ]\t"
 +[ $a < $b ] && echo "​TRUE"​ || echo "​FALSE"​
 +
 +echo -ne "[ $a \< $b ]\t"
 +[ $a \< $b ] && echo "​TRUE"​ || echo "​FALSE"​
 +
 +echo -ne "[[ $a < $b ]]\t"
 +[[ $a < $b ]]  && echo "​TRUE"​ || echo "​FALSE"​
 +
 +echo -ne "[[ $a -lt $b ]]\t"
 +[[ $a -lt $b ]]  && echo "​TRUE"​ || echo "​FALSE"​
 +
 +echo -ne "[ $a -lt $b ]\t"
 +[ $a -lt $b ] && echo "​TRUE"​ || echo "​FALSE"​
 +
 +echo -ne "test $a -lt $b\t"
 +test $a -lt $b  && echo "​TRUE"​ || echo "​FALSE"​
  
-Numeric comparisons:​ 10 less than 2 should be FALSE +echo -ne "(( $a $b ))\t" 
------------------------------------- +(( $a < $b ))  &&​ echo "TRUE" || echo "FALSE"
-[ 10 < 2 ] numeric_comparisons.bash:​ line 41: 2: No such file or directory +
-FALSE +
-[ 10 \< 2 ] TRUE +
-[[ 10 < 2 ]] TRUE +
-[[ 10 -lt 2 ]] FALSE +
-[ 10 -lt 2 ] FALSE +
-test 10 -lt 2 FALSE +
-(( 10 )) FALSE +
-(( 10 -lt 2 )) numeric_comparisons.bash:​ line 63: ((: 10 -lt 2 : syntax error in expression (error token is ""+
-FALSE+
  
 +echo -ne "(( $a -lt $b ))\t"
 +(( $a -lt $b ))  && echo "​TRUE"​ || echo "​FALSE"​
 +</​code>​
2018numeric_cmp.1536339599.txt.gz · Last modified: 2018/09/07 10:59 by david