Expr - Bourne Shell Expression Evaluator
This section is on the expr command, used to perform expression evaluation.
The Bourne shell didn't originally have any mechanism to perform simple arithmetic. In older versions
of UNIX, it used external programs, either awk or the must simpler program expr. In UNIX System V,
and therefore in Solaris, expr was added to the Bourne shell, which increases the speed of any Bourne
shell script that uses the built-in version. If the full path-name is used, the external version is executed,
causing a slight speed penalty. There are four types of operations expr performs:
Arithmetic
Logical
Relational
String
Most of the operators are obvious:
+-------------------------------------------------+
|Operator
Type Meaning
|
+-------------------------------------------------+
|
+
Arithmetic Addition
|
|
-
Arithmetic Subtraction
|
|
*
Arithmetic Multiplication
|
|
/
Arithmetic Division
|
|
%
Arithmetic Remainder
|
+-------------------------------------------------+
|
=
Relational Equal to
|
|
>
Relational Greater Than
|
|
>=
Relational Greater Than or Equal to |
|
<
Relational Less Than
|
|
<=
Relational Less than or Equal to |
|
!=
Relational Not Equal to
|
+-------------------------------------------------+
|
|
Boolean Or
|
|
&
Boolean And
|
+-------------------------------------------------+
|
:
String Match or substitute |
+-------------------------------------------------+
Not so obvious is how to use these operators. The general form is
expression operator expression
First of all, there must be spaces between operators and expressions. The example below is incorrect:
expr 2+2
The proper form is
expr 2 + 2
which prints "4" to standard output. The second concern is the shell, which treats some of the
characters as meta characters. Therefore if you use any of these characters "*&|><()" you must place a
backslash before them, or put quotes around them. Examples:
Bourne Shell Tutorial
http://www.grymoire.com/Unix/Sh.html
52 of 66
11/21/2011 12:03 PM
# 2 times 10
expr 2 "*" 10
# or
expr 2 \* 10
# a complex expression
# true if both $a and $b are greater than zero
expr $a '>' 0 '&' $b '>' 0
# But this gives you an error if $a or $b are undefined
# so you should use
expr "$a" '>' 0 '&' "$b" '>' 0
The third potential problem is quoting too many characters. The expression
expr '2 + 2'
is not "4" but "2 + 2" which is five characters long. This allows strings with spaces to be compared:
expr $a = '2 + 2'
If only one expression is given, then expr simply echos it.
expr no
prints the word "no."
Another potential problem is variables that contain operators. The following example, which looks like it
might test if a variable is equal to an "=," generates an error:
A='='
# is $A an '='?
expr $A = '='
# WRONG - syntax error - same as 'expr = = ='
The fix is similar to the one used to fix test, i.e. add an extra character before the variable:
expr X$A = X=
Arithmetic Operators
Expr uses 32-bit, signed integers. Therefore negative numbers are acceptable. A common use is loops:
# count from 1 to 10
A=1
while [ $A -le 10 ]
do
echo $A
A=`expr $A + 1`
done
Relational Operators
Bourne Shell Tutorial
http://www.grymoire.com/Unix/Sh.html
53 of 66
11/21/2011 12:03 PM
The relational operators check to see if both expressions are integers. If so, the comparison is numeric. If one
or more expressions are non-numeric, the comparison is lexical. Therefore you can compare integers or
strings. The confusing part of the relational operators is deciding how to use the information. You see, the
operators output to standard output, and also return an exit status. Remember how the value of true is
typically non-zero, but a true exit status is zero? Well, expr continues this tradition. Consider the following
test:
expr 1 = 1
This outputs "1," or "true" to standard output, but returns an exit status of zero. To be precise, if the
expression has a value that is not equal to zero, and not equal to a null string, then the exit status is zero. An
exit status of one is the opposite, i,e, the output is a null string or zero. Expr will return an exit status of 2 if an
error occurs. The exit status can be used in simple tests:
expr $A = 1 > /dev/null && echo A = 1
Notice how the standard output had to be discarded, otherwise the script would print out a "1." The
expression can also be used in a loop:
A=1;
while expr $A '<=' 10 >/dev/null
do
A=`expr $A + 1`
echo $A
done
Relational operators always print a zero or one.
Boolean Operators
The two boolean operators operate on strings and integers. A null string and a zero are false. Anything else is
true. I mentioned the status before. This is a "side-effect," because the program also sends a string to standard
output. In other words, the designers of the expr program tried to make it as versatile as possible. Consider
the following:
expr $a & $b
If either variable is an empty string, or zero, the program prints zero. (The status is one.) If not, the program
exits with a status of zero, but it does not print a one. instead, it prints the value of variable "a." Imagine
Garry Owens or Don Pardo saying
Not only does expr return a status, but it prints too! And it doesn't just print zero or one. It prints
either zero, or the actual value of the expression, saving you time and money.
On the other hand, they may have simply felt printing a one would throw away information for no reason. The
"|" operator also returns zero if both expressions are zero or a null string. Otherwise, it returns either the first
expression, or the second. More precisely, expr looks at the first expression, and if not a zero or null, it
returns the value, otherwise it returns the second expression, not even checking its value. This is a little
confusion. A table might help. The first column is the expression. The second is the printout. The third column
is the exit status:
Bourne Shell Tutorial
http://www.grymoire.com/Unix/Sh.html
54 of 66
11/21/2011 12:03 PM