expr — Evaluate an expression (POSIX arithmetic / string ops) across all 5 shells
Equivalents in every shell
expr 2 + 3External in `/usr/bin/expr`. Each operand MUST be a separate argument (`expr 2+3` prints the literal `2+3`). Multiplication needs `\*` to escape glob expansion. Exit status: 0 if value non-zero/non-empty, 1 if zero/empty, 2 on syntax error. Mostly superseded by `$(( ))`.
expr 2 + 3Same external. Idiomatic zsh prefers `(( count++ ))` / `$(( a + b ))` for arithmetic and `${var#prefix}` / `${var:offset:len}` for string ops. `expr` survives mostly for POSIX `/bin/sh` script portability.
math 2 + 3Fish builtin (3.0+). Accepts floats and named functions: `math "sin(pi/2)"`, `math -s 2 1/3` (scale). For string ops use `string sub`, `string match`, `string length` — they replace expr's substring / match / length forms.
2 + 3PowerShell evaluates expressions natively — `2 + 3`, `"abc".Length`, `"hello world" -match "world"` need no helper. `[math]::Sqrt(16)` covers transcendentals. No `expr`-style argument-per-operand splitting.
set /a result=2+3`set /a` is the only built-in arithmetic. Integer-only, signed 32-bit. Operators: `+ - * / % & | ^ ~ << >>`. NO string-length, substring, or regex operators — string work needs `for /f` loops or PowerShell.
Worked examples
Add two numbers
expr 2 + 3echo $((2 + 3))math 2 + 32 + 3set /a 2+3Get the length of a string
expr length 'hello world's='hello world'; echo ${#s}string length 'hello world'"hello world".LengthExtract a number from a tagged identifier
expr 'build-123' : '.*-\([0-9]*\)'string match -r -- '\d+' build-123if ('build-123' -match '\d+') { $Matches[0] }Gotchas
- `expr` REQUIRES spaces around every operator AND each operand as a separate shell argument. `expr 2+3` prints the literal `2+3`. `expr 2 * 3` glob-expands `*` to filenames — escape as `\*` or quote `"*"`. The argument-splitting model is a constant footgun.
- Exit status INVERTS the usual convention: `0` when the result is non-zero / non-empty, `1` when zero / empty, `2` on syntax error. With `set -e` this aborts on `n=$(expr 0 + 0)` because the zero result returns 1. Wrap in `... || true` or use `$(( ))` instead.
- Arithmetic substitution `$(( 2 + 3 ))` replaces 90 % of `expr` use cases — same POSIX guarantee, no subprocess, no escaping required. Reach for `expr` only when targeting pre-POSIX shells or one of its rarer string-op forms like `expr length` / `expr index`.
- Fish's `math` accepts FLOATS (`math 1/3` → `0.333333`), where bash `$(( 1/3 ))` and `expr 1 / 3` return integer `0`. For decimal arithmetic in bash, pipe through `bc -l` or use `awk 'BEGIN{print 1/3}'` — bash itself has no native floating-point.
- PowerShell has NO `expr` cmdlet and DELIBERATELY no shell-style "evaluate this string" primitive. `Invoke-Expression` exists but runs arbitrary code (the PS equivalent of `eval`) — never feed it untrusted input. For pure math, just write the expression; the parser evaluates it.