As mentioned in,“Shell Script Basics,” the shell scripting language contains basic equality testing without the use of the expr command. For example:
if [ 1 = 2 ] ; then |
echo "equal" |
else |
echo "not equal" |
fi |
This code will work as expected. However, it isn't doing what you might initially think it is doing; this is performing a string comparison, not a numeric comparison. Thus the following code will not behave the way you would expect if you assumed it was comparing the numerical values:
if [ 1 = "01" ] ; then |
echo "equal" |
else |
echo "not equal" |
fi |
It will print the words "not equal", as the strings "1" and "01" are not the same string.
Warning: Do not inadvertently perform a redirect instead of an inequality test. Take the following code for example:
if [ 2 > 3 ] ; then |
echo greater |
fi |
The same thing occurs if you use the expr command without enclosing the less than or greater than operators in quotes.
This can also be a problem even when working with the expr command if your script takes user input. The expr command expects a number or symbol per argument. If you feed it something that isn't just a number or symbol, it will treat it as a string, and will perform string comparison instead of numeric comparison.
The following code demonstrates this in action:
expr '1' '+' '2' |
expr ' 1' '+' '2' |
expr '2' '<' '1' |
expr ' 2' '<' '1' |
The first line will print the number 3. The second line will give an error message. When doing addition, this is easy to detect. When doing comparisons, however, as shown in the following two lines, the results are more insidious. The number 2 is clearly greater than the number 1. In string comparison, however, a space sorts before any letter or number. Thus, the third line prints a 0, while the fourth line prints a 1. This is probably not what you want.
As with most things in shell scripting, there are many ways to solve this problem, depending on your needs. If you are only worried about spaces, and if the purpose for the comparison is to control shell execution, you can use the numeric evaluation routines built into test, as described in the test man page.
For example:
MYNUMBER=" 2" # Note this is a string, not a number. |
# Force an integer comparison. |
if [ "$MYNUMBER" -gt '1' ] ; then |
echo 'greater' |
fi |
However, while this works for trivial cases, there are a number of places where this is not sufficient. For example, this cannot be used if:
Floating point comparison is needed (as described in “Beyond Basic Math”).
The value is preceded by a dollar sign or similar.
The intended use is as a numerical truth value in a more complicated mathematical expression (without splitting the expression).
A common way to solve such problems is to process the arguments with a regular expression. For example, to strip any non-numeric characters from a number, you could do the following:
MYRAWNUMBER=" 2" # Note this is a string, not a number. |
# Strip off any characters that aren't in the range of 0-9 |
MYNUMBER="$(echo "$MYRAWNUMBER" | sed 's/[^0-9]//g')" |
expr "$MYNUMBER" '<' '1' |
This would result in a comparison between the number 2 and the number 1, as expected.
For more information on regular expressions, see “Regular Expressions Unfettered.”
Last updated: 2008-04-08