[TUHS] Arithmetic expansion in Unix shells
Brian Walden
tuhs at cuzuco.com
Wed Jun 23 01:52:36 AEST 2021
even tho it was there, in-shell integer arithmetic had a few
issues before ksh86.
pre-ksh86 these had problems --
A. decimal point in a number
$ integer I
$ I=2.2
would error on the assignment, but with ksh86 $I is truncated to 2
(yes "integer" is an builtin alias to typeset -i and ksh courses at the time
instructed to use that over typset)
B. negative numbers
$ integer I
$ I=-2
here pre-86 $I would be assigned a large value like 2147483646
also ksh was not stardard until SVR4 (very late 80s) so it was found
in paths like /usr/add-on/bin/ksh or /usr/exptools/bin/ksh, or not even
there at all, you could not reliably #! ksh scripts
also with ksh86 the double paren ((...)) notation was exactly the same as
"let ..." and were completely optional if the variable was predefined as
an integer, so
$ I=0
$ ((I=I+1))
and
$ integer I
$ I=0
$ I=I+1
are the same.
All internal integers in ksh were C longs (at least 32-bits)
where Bourne shell all vars are strings so you would need to do this --
$ I=`expr $I + 1`
But also at that time expr(1) could NOT deal with negative numbers on input,
they became strings. So
$ expr -9 + 1
is an error with "non-numeric argument", and
$ expr -11 '<' -1
returns 0, a false statement, which are hidden bugs with variables.
expr(1) was also 32-bits, as was test (i.e [ ) which could deal with
negative numbers just fine.
for arbitrarily large numbers you needed use dc(1) or bc(1). but dc(1)
also has a issue with inputing negative numbers as it uses an _ not
a - to denote a negatve number on input, but does use the - on output.
$ I=`echo _9 1 - p | dc`
is how you would do ((I=-9 - 1)) in bourne with dc
which is cumbersome if you have a variable with a neagtive number in it,
and required a "tr - _" first.
however
$ I=`echo -9 - 1 | bc`
worked just fine in bourne.
-Brian
Chet Ramey wrote:
> On 6/21/21 5:57 AM, arnold at skeeve.com wrote:
> > Arithmetic expansion dates back at least as far as ksh88.
>
> ksh had the `let' builtin from at least 1983. The ((...)) compound command
> was there by ksh-86.
>
> > Bash likely picked it up from there.
>
> Sort of, see below.
>
> > The original was only integer math and Bash remains that way (IIRC,
> > Chet can correct me if I'm wrong). ksh93 added floating point math.
>
> Yes, bash only has integer arithmetic, since it's all POSIX requires.
>
> > POSIX would have picked it up from ksh88.
>
> The $((...)) form of arithmetic expansion is something POSIX picked up
> from ksh-88, eventually. The early drafts of the standard (through 1003.2
> d9, at least), used $[...], but they eventually adopted $((...)) because
> ksh-88 had already implemented it, though it's not documented in Bolsky
> and Korn.
>
> I put $[...] into bash first (it's still there, though deprecated), then
> `let', then $((...)) after POSIX added it, and finally `((' for
> compatibility.
>
> Chet
More information about the TUHS
mailing list