expr(1b) on Solnix vs Linux and the BSDs
This page documents the BSD-compatibility /usr/ucb/expr, not the /usr/bin/expr that a default Solnix system has on PATH. The page describes 32-bit integers and the keywords match, substr, index and length. It warns that those keywords cannot be used as plain strings and that negative substr arguments can make expr run forever.
The manual pages
- Solnix: expr(1b) from
pkgs.solnix.illumos-world-man· illumos.org - Linux: expr(1) coreutils-full-9.11
- FreeBSD: expr(1) 15.1-RELEASE
- OpenBSD: expr(1) 8.0
- NetBSD: expr(1) 11.0
- Standard: POSIX.1-2024 (IEEE Std 1003.1-2024),
expr
What Solnix runs
A default Solnix system runs the illumos expr at /usr/bin/expr. The illumos variants /usr/xpg4/bin/expr, /usr/xpg6/bin/expr and /usr/ucb/expr are also shipped. This page, expr(1b), has the synopsis '/usr/ucb/expr argument...' and the bundle contains no text for /usr/bin/expr or the xpg variants. The differences below therefore describe the /usr/ucb/expr page and may not hold for /usr/bin/expr.
Differences
| Compared with | Topic | What differs |
|---|---|---|
| FreeBSD, NetBSD | integer width | Solnix /usr/ucb/expr treats integers as 32-bit two's-complement numbers. FreeBSD uses intmax_t and NetBSD uses 64 bits, and both check for overflow. NetBSD says 32-bit expr only handles -2147483648 to +2147483647.Source: Solnix expr(1b) DESCRIPTION; FreeBSD expr(1) DESCRIPTION; NetBSD expr(1) COMPATIBILITY |
| Linux, OpenBSD | integer width (undocumented) | The Linux and OpenBSD pages do not state the integer range or overflow behaviour, so a comparison with the Solnix 32-bit limit cannot be made from the manuals. Source: Linux expr(1) DESCRIPTION; OpenBSD expr(1) DESCRIPTION; Solnix expr(1b) DESCRIPTION |
| FreeBSD, OpenBSD, NetBSD | match, substr, index keywords | Solnix and Linux document match, substr, index and length. FreeBSD treats these words as ordinary strings. NetBSD documents only length, as a GNU-compatible extension. The OpenBSD page documents none of them. Source: Solnix expr(1b) operators list; Linux expr(1) substr, index, length; FreeBSD expr(1) STANDARDS; NetBSD expr(1) STANDARDS; OpenBSD expr(1) DESCRIPTION |
| Linux | keywords as plain strings | On Solnix, match, substr, length and index cannot be used as ordinary strings. 'expr index expurgatorious length' gives 'syntax error'. The workaround is to prefix an operand, as in expr X$a = X=. Linux has a '+ TOKEN' form to force a string. Source: Solnix expr(1b) BUGS; Linux expr(1) '+ TOKEN' |
| FreeBSD | operand that looks like an operator | Solnix says that after shell expansion expr cannot tell an operator from an operand, so 'expr $a = =' with $a set to = is misread. FreeBSD calls an operand identical to an operator a syntax error and points to its examples for a workaround. Source: Solnix expr(1b) BUGS; FreeBSD expr(1) DESCRIPTION |
| Linux | negative substr arguments | Solnix warns that negative values for substr's integer-1 or integer-2 can make expr run forever. Linux documents substr POS as counted from 1 and says nothing about negative values. Source: Solnix expr(1b) substr; Linux expr(1) substr |
| NetBSD | length unit | Solnix length returns the number of characters. NetBSD length returns the length in bytes. Source: Solnix expr(1b) length; NetBSD expr(1) length expr |
| Linux | exit status 3 | Linux expr exits 3 when an error occurred. The Solnix page lists only 0, 1 and 2. Source: Solnix expr(1b) EXIT STATUS; Linux expr(1) DESCRIPTION (exit status) |
| OpenBSD, NetBSD | exit status above 2 | OpenBSD and NetBSD document an exit status greater than 2 for errors such as memory allocation failure. The Solnix page lists only 0, 1 and 2. Source: Solnix expr(1b) EXIT STATUS; OpenBSD expr(1) EXIT STATUS; NetBSD expr(1) EXIT STATUS |
| FreeBSD, OpenBSD, NetBSD | failed match with a subexpression | On FreeBSD, OpenBSD and NetBSD a failed match returns the null string when the pattern contains \(...\), and 0 otherwise. The Solnix page says only that the match returns the number of characters matched, 0 on failure. Source: Solnix expr(1b) string : regular-expression; FreeBSD, OpenBSD and NetBSD expr(1) ':' operator |
| FreeBSD, OpenBSD, NetBSD | regular expression syntax | The BSD pages say the ':' pattern is a basic regular expression (NetBSD says a regular expression). Solnix defers to regexp(7), anchored at the start, so ^ is not special. Source: Solnix expr(1b) matching operator; FreeBSD expr(1) ':'; OpenBSD expr(1) ':'; NetBSD expr(1) ':' |
| FreeBSD | -e option and EXPR_COMPAT | FreeBSD expr accepts -e and reads EXPR_COMPAT for backwards-compatible number parsing. A leading argument beginning with a minus sign is treated as an option unless -- is used. The Solnix page documents no options and no environment variables.Source: FreeBSD expr(1) SYNOPSIS, ENVIRONMENT, Compatibility; Solnix expr(1b) SYNOPSIS |
| OpenBSD, NetBSD | matching the empty string | OpenBSD and NetBSD document that expr '' : '$' fails, and suggest a prefix such as X'' : 'X$'. The Solnix page does not mention this case. Source: OpenBSD expr(1) ':' note; NetBSD expr(1) NOTES; Solnix expr(1b) matching operator |
Standards
- POSIX: expr is a POSIX.1-2024 utility.
- Solnix: The expr(1b) page has no STANDARDS section. It refers to attributes(7) but the bundle does not show its contents.
- FreeBSD: The expr utility conforms to IEEE Std 1003.1-2008 (“POSIX.1”), provided that backwards compatibility mode is not enabled. The
-eflag is an extension. - OpenBSD: The expr utility is compliant with the IEEE Std 1003.1-2008 (“POSIX.1”) specification.
- NetBSD: The expr utility conforms to IEEE Std 1003.2 (“POSIX.2”). The length keyword is an extension for compatibility with GNU expr.
Writing portable scripts
- Do not rely on match, substr, index or length. FreeBSD treats them as plain strings and OpenBSD does not document them. Use shell parameter expansion or a regular expression with ':' instead.
- Prefix operands that might look like operators or keywords with a fixed character, for example expr X$a = X=, and test the exit status as 0, 1 or 2 only.
Every difference here is taken from the manual pages linked above: Solnix's published page, Linux (man-pages and the GNU and util-linux manuals), FreeBSD, OpenBSD and NetBSD. Each row names its source. Where a manual is silent, this page is too. Compiled 2026-10-26. Found a mistake? Mail hackers@lists.solnix.io.