expr does not seem to like parenthesis (used in mathematics to explicit operator priority):
expr 3 * (2 + 1) bash: syntax error near unexpected token `('
How to express operator priority in bash?
You can use the arithmetic expansion instead.
echo "$(( 3 * ( 2 + 1 ) ))" 9
In my personal opinion, this looks a bit nicer than using
Arithmetic Expansion Arithmetic expansion allows the evaluation of an arithmetic expression and the substitution of the result. The format for arithmetic expansion is:
The expression is treated as if it were within double quotes, but a double quote inside the parentheses is not treated specially. All tokens in the expression undergo parameter expansion, string expansion, command substitution, and quote removal. Arithmetic expansions may be nested.
The evaluation is performed according to the rules listed below under ARITHMETIC EVALUATION. If expression is invalid, bash prints a message indicating failure and no substitution occurs.
There's no reason to be using
expr for arithmetic in modern shells.
POSIX defines the
$((...)) expansion operator. So you can use that in all POSIX compliant shells (the
sh of all modern Unix-likes, dash, bash, yash, mksh, zsh, posh, ksh...).
a=$(( 3 * (2 + 1) )) a=$((3*(2+1)))
ksh also introduced a
let builtin which is passed the same kind of arithmetic expression, doesn't expand into something but returns an exit status based on whether the expression resolves to 0 or not, like in
if let 'a = 3 * (2 + 1)'; then echo "$a is non-zero" fi
However, as the quoting makes it awkward and not very legible (not to the same extent as
expr of course),
ksh also introduced a
((...)) alternative form:
if (( a = 3 * (2 + 1) )) && (( 3 > 1 )); then echo "$a is non-zero and 3 > 1" fi ((a+=2))
which is a lot more legible and should be used instead.
((...)) are only available in
$((...)) syntax should be preferred if portability to other shells is needed,
expr is only needed for pre-POSIX Bourne-like shells (typically the Bourne shell or early versions of the Almquist shell).
On the non-Bourne front, there are a few shells with built-in arithmetic operator:
tcsh (actually the first Unix shell with arithmetic evaluation built-in):
@ a = 3 * (2 + 1)
akanga (based on
a = $:'3 * (2 + 1)'
as a history note, the original version of the Almquist shell, as posted on usenet in 1989 had an
expr builtin (actually merged with
test), but it was removed later.
expr is an external command, it is not special shell syntax. Therefore, if you want
expr to see shell special characters, you need to protect them from shell parsing by quoting them. Furthermore,
expr needs each number and operator to be passed as a separate parameter. Thus:
expr 3 \* \( 2 + 1 \)
Unless you're working on an antique unix system from the 1970s or 1980s, there is very little reason to use
expr. In the old days, shells didn't have a built-in way to perform arithmetic, and you had to call the
expr utility instead. All POSIX shells have built-in arithmetic via the arithmetic expansion syntax.
echo "$((3 * (2 + 1)))"
$((…)) expands to the result of the arithmetic expression (written in decimal). Bash, like most shells, supports only integer arithmetic modulo 264 (or modulo 232 for older versions of bash and some other shells on 32-bit machines).
Bash offers an additional convenience syntax when you want to perform assignments or to test whether an expression is 0 but don't care about the result. This construct also exists in ksh and zsh but not in plain sh.
((x = 3 * (2+1))) echo "$x" if ((x > 3)); then …
In addition to integer arithmetic,
expr offers a few string manipulation functions. These too are subsumed by features of POSIX shells, except for one:
expr STRING : REGEXP tests whether the string matches the specified regexp. A POSIX shell cannot do this without external tools, but bash can with
[[ STRING =~ REGEXP ]] (with a different regexp syntax —
expr is a classic tool and uses BRE, bash uses ERE).
Unless you're maintaing scripts that run on 20-year-old systems, you don't need to know that
expr ever existed. Use shell arithmetic.