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 12:49]
david
2018numeric_cmp [2018/09/07 14:02] (current)
david [Incorrect Numeric Comparisons (lexicographic order)]
Line 1: Line 1:
 +~~NOTOC~~
 ====== Comparison operators in BASH ====== ====== Comparison operators in BASH ======
  
-The multiple constructs that are available in BASH can lead to confusion. ​To distinguish numeric versus alphanumeric comparisons (sorting strings, like filenames), follow these rules: +The multiple constructs that are available in BASH can lead to confusion. ​
-  * To compare values numerically,​ you can use the flag operators -lt (less than),-gt (greater than), -eq (equal to), -ne (not equal), -ge (greater or equal to), -le (less than or equal to): +
-    * With single brackets [ ] +
-    * With double brackets <​nowiki>​[[ ]]</​nowiki>​+
  
 +===== 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'': ​ For example, say ''​a=2''​ and ''​b=10'': ​
-   * <​nowiki>​[ ​$a -lt $b ]</​nowiki>​ is TRUE +  ​* <​nowiki>​[ ​-lt 10 ]</​nowiki>​ is TRUE 
-   ​* <​nowiki>​[[ ​$a -lt $b ]]</​nowiki>​ is TRUE +  * <​nowiki>​[[ ​-lt 10 ]]</​nowiki>​ is TRUE 
-   ​* <​nowiki>​[[ ​$a -ge $b ]]</​nowiki>​ is FALSE+  * <​nowiki>​[[ ​-ge 10 ]]</​nowiki>​ is FALSE 
 +  * <​nowiki>​(( 2 < 10 ))</​nowiki>​ is TRUE
  
-What results in an alphanumeric comparison (which ​you don't want), or a syntax error (which you might not see) is the following:​ +===== Incorrect Numeric Comparisons (lexicographic order) ===== 
-  * <​nowiki>​[[ ​$a $b ]]</​nowiki>,​ alphanumerically FALSE +What results in an alphanumeric comparison (which ​has unexpected behavior), or a syntax error (which you may overlook) is the following:​ 
-  * <​nowiki>​[ ​$a $b ]</​nowiki>,​ error; also FALSE.+  * <​nowiki>​[[ ​10 ]]</​nowiki>,​ alphanumerically FALSE 
 +  * <​nowiki>​[ ​10 ]</​nowiki>,​ error; also FALSE.
  
-Alternatively,​ a numeric comparison is valid with parentheses:​ +===== Importance of Testing =====
-  * <​nowiki>​(( $a < $b ))</​nowiki>​ is TRUE+
  
----- +Whenever I have a question about a confusing ​syntax ​issueI write 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:
- +
-It can be difficult to keep track of which constructs are OK in different situations, but here are some rules in BASH: +
-  * ''<​nowiki>​[ expr ]</​nowiki>'',​ ''​expr''​ is evaluated as BASH command ​syntax, ​which has special meaning for some of the symbol operators. +
-  * ''<​nowiki>​[[ expr ]]</​nowiki>'', ​"​safer"​ alternative to the single brackets, as there is less command parsing +
-  * ''<​nowiki>​(( expr ))</​nowiki>'',​ ''​expr''​ is assumed ​to contain ​the symbol operators. +
- +
-Testing is very important. To distinguish between the correct, incorrect, and error-producing constructs, I wrote a script that produces this table:+
  
 ^ Syntax ^ Output ^  Error  ^ ^ Syntax ^ Output ^  Error  ^
Line 50: Line 48:
 | ''<​nowiki>​(( 10 -lt 2 ))</​nowiki>''​ | FALSE | ''<​nowiki>​((:​ 10 -lt 2 : syntax error (error token is "2 "​)</​nowiki>''​ | | ''<​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"​
 +
 +echo -ne "(( $a < $b ))\t"
 +(( $a < $b ))  && echo "​TRUE"​ || echo "​FALSE"​
  
 +echo -ne "(( $a -lt $b ))\t"
 +(( $a -lt $b ))  && echo "​TRUE"​ || echo "​FALSE"​
 +</​code>​
2018numeric_cmp.1536346155.txt.gz · Last modified: 2018/09/07 12:49 by david