This is an old revision of the document!
The multiple constructs that are available in BASH can lead to confusion.
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
:
What results in an alphanumeric comparison (which has unexpected behavior), or a syntax error (which you may overlook) is the following:
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 |
---|---|---|
Numeric comparisons: 2 less than 10 should be TRUE | ||
[ 2 < 10 ] | FALSE | 10: No such file or directory |
[ 2 \< 10 ] | FALSE | |
[[ 2 < 10 ]] | FALSE | |
[[ 2 -lt 10 ]] | TRUE | |
[ 2 -lt 10 ] | TRUE | |
[ "2" -lt "10" ] | TRUE | |
test 2 -lt 10 | TRUE | |
(( 2 < 10 )) | TRUE | |
(( 2 -lt 10 )) | FALSE | ((: 2 -lt 10 : syntax error (error token is "10 ") |
Numeric comparisons: 10 less than 2 should be FALSE | ||
[ 10 < 2 ] | FALSE | 2: No such file or directory |
[ 10 \< 2 ] | TRUE | |
[[ 10 < 2 ]] | TRUE | |
[[ 10 -lt 2 ]] | FALSE | |
[ 10 -lt 2 ] | FALSE | |
test 10 -lt 2 | FALSE | |
(( 10 < 2 )) | FALSE | |
(( 10 -lt 2 )) | FALSE | ((: 10 -lt 2 : syntax error (error token is "2 ") |
This script is:
#!/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"