1.\"	$NetBSD: expr.1,v 1.40 2025/03/15 22:01:16 rillig Exp $
2.\"
3.\" Copyright (c) 2000, 2003, 2025 The NetBSD Foundation, Inc.
4.\" All rights reserved.
5.\"
6.\" This code is derived from software contributed to The NetBSD Foundation
7.\" by J.T. Conklin <jtc@NetBSD.org> and Jaromir Dolecek <jdolecek@NetBSD.org>.
8.\"
9.\" Redistribution and use in source and binary forms, with or without
10.\" modification, are permitted provided that the following conditions
11.\" are met:
12.\" 1. Redistributions of source code must retain the above copyright
13.\"    notice, this list of conditions and the following disclaimer.
14.\" 2. Redistributions in binary form must reproduce the above copyright
15.\"    notice, this list of conditions and the following disclaimer in the
16.\"    documentation and/or other materials provided with the distribution.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28.\" POSSIBILITY OF SUCH DAMAGE.
29.\"
30.Dd March 15, 2025
31.Dt EXPR 1
32.Os
33.Sh NAME
34.Nm expr
35.Nd evaluate expression
36.Sh SYNOPSIS
37.Nm
38.Ar operand ...
39.Sh DESCRIPTION
40The
41.Nm
42utility evaluates the expression consisting of the
43.Ar operand
44arguments and writes the result on standard output.
45.Pp
46Each operand is a separate argument to the
47.Nm
48utility.
49Characters special to the command interpreter must be escaped.
50.Pp
51Operators are listed below in order of increasing precedence.
52Operators with equal precedence are grouped within { } symbols.
53.Bl -tag -width indent
54.It Ar expr1 Li \&| Ar expr2
55Returns the evaluation of
56.Ar expr1
57if it is neither an empty string nor zero;
58otherwise, returns the evaluation of
59.Ar expr2
60if it is not empty;
61otherwise, returns zero.
62.It Ar expr1 Li & Ar expr2
63Returns the evaluation of
64.Ar expr1
65if neither expression evaluates to an empty string or zero;
66otherwise, returns zero.
67.It Ar expr1 Li "{=, >, >=, <, <=, !=}" Ar expr2
68Returns the result of the integer comparison if both arguments are integers;
69otherwise, returns the result of the string comparison
70using the locale-specific collation sequence.
71The result of each comparison is 1 if the specified relation is true,
72or 0 if the relation is false.
73.It Ar expr1 Li "{+, -}" Ar expr2
74Returns the result of addition or subtraction of integer-valued arguments.
75.It Ar expr1 Li "{*, /, %}" Ar expr2
76Returns the result of multiplication, integer division, or remainder
77of integer-valued arguments.
78.It Ar expr1 Li \&: Ar expr2
79The
80.Dq \&:
81operator matches
82.Ar expr1
83against
84.Ar expr2 ,
85the latter must be a regular expression.
86The regular expression is anchored
87to the beginning of the string with an implicit
88.Dq ^ .
89.Pp
90If the match succeeds and the pattern contains at least one regular
91expression subexpression
92.Dq "\e(...\e)" ,
93the string corresponding to
94.Dq "\e1"
95is returned;
96otherwise the matching operator returns the number of characters matched.
97If the match fails and the pattern contains a regular expression subexpression,
98the empty string is returned;
99otherwise 0.
100.It "( " Ar expr No " )"
101Parentheses are used for grouping in the usual manner.
102.El
103.Pp
104Additionally, the following keywords are recognized:
105.Bl -tag -width indent
106.It length Ar expr
107Returns the length of the specified string in bytes.
108.El
109.Pp
110Operator precedence (from highest to lowest):
111.Bl -enum -compact -offset indent
112.It
113parentheses
114.It
115length
116.It
117.Dq \&:
118.It
119.Dq "*" ,
120.Dq "/" ,
121and
122.Dq "%"
123.It
124.Dq "+"
125and
126.Dq "-"
127.It
128compare operators
129.It
130.Dq &
131.It
132.Dq \&|
133.El
134.Sh EXIT STATUS
135The
136.Nm
137utility exits with one of the following values:
138.Bl -tag -width Ds -compact
139.It 0
140the expression is neither an empty string nor 0.
141.It 1
142the expression is an empty string or 0.
143.It 2
144the expression is invalid.
145.It >2
146an error occurred (such as memory allocation failure).
147.El
148.Sh EXAMPLES
149.Bl -enum
150.It
151The following example adds one to variable
152.Dq a :
153.Dl a=`expr $a + 1`
154.It
155The following example returns zero, due to subtraction having higher precedence
156than the
157.Dq &
158operator:
159.Dl expr 1 '&' 1 - 1
160.It
161The following example returns the filename portion of a pathname stored
162in variable
163.Dq a :
164.Dl expr "/$a" Li : '.*/\e(.*\e)'
165.It
166The following example returns the number of characters in variable
167.Dq a :
168.Dl expr $a Li : '.*'
169.El
170.Sh COMPATIBILITY
171This implementation of
172.Nm
173internally uses 64 bit representation of integers and checks for
174over- and underflows.
175It also treats
176.Dq /
177(the division mark) and option
178.Dq --
179correctly depending upon context.
180.Pp
181.Nm
182on other systems (including
183.Nx
184up to and including
185.Nx 1.5 )
186might not be so graceful.
187Arithmetic results might be arbitrarily
188limited on such systems, most commonly to 32 bit quantities.
189This means such
190.Nm
191can only process values between -2147483648 and +2147483647.
192.Pp
193On other systems,
194.Nm
195might also not work correctly for regular expressions where
196either side contains
197.Dq /
198(a single forward slash), like this:
199.Bd -literal -offset indent
200expr / : '.*/\e(.*\e)'
201.Ed
202.Pp
203If this is the case, you might use
204.Dq //
205(a double forward slash)
206to avoid confusion with the division operator:
207.Bd -literal -offset indent
208expr "//$a" : '.*/\e(.*\e)'
209.Ed
210.Pp
211According to
212.St -p1003.2 ,
213.Nm
214has to recognize the special option
215.Dq -- ,
216treat it as a delimiter to mark the end of command
217line options, and ignore it.
218Some
219.Nm
220implementations do not recognize it at all; others
221might ignore it even in cases where doing so results in syntax
222error.
223There should be the same result for both following examples,
224but it might not always be:
225.Bl -enum -compact -offset indent
226.It
227expr -- : .
228.It
229expr -- -- : .
230.El
231Although
232.Nx
233.Nm
234handles both cases correctly, you should not depend on this behavior
235for portability reasons and avoid passing a bare
236.Dq --
237as the first
238argument.
239.Sh STANDARDS
240The
241.Nm
242utility conforms to
243.St -p1003.2 .
244The
245.Ar length
246keyword is an extension for compatibility with GNU
247.Nm .
248.Sh HISTORY
249An
250.Nm
251utility first appeared in the Programmer's Workbench (PWB/UNIX).
252A public domain version of
253.Nm
254written by
255.An Pace Willisson
256.Aq pace@blitz.com
257appeared in
258.Bx 386 0.1 .
259.Sh AUTHORS
260Initial implementation by
261.An Pace Willisson Aq Mt pace@blitz.com
262was largely rewritten by
263.An -nosplit
264.An J.T. Conklin Aq Mt jtc@NetBSD.org .
265It was rewritten again for
266.Nx 1.6
267by
268.An -nosplit
269.An Jaromir Dolecek Aq Mt jdolecek@NetBSD.org .
270.Sh NOTES
271The empty string
272.Do Dc
273cannot be matched with the intuitive:
274.Bd -literal -offset indent
275expr '' : '$'
276.Ed
277.Pp
278The reason is that the returned number of matched characters (zero)
279is indistinguishable from a failed match, so this returns failure.
280To match the empty string, use something like:
281.Bd -literal -offset indent
282expr x'' : 'x$'
283.Ed
284