I know how to create an arithmetic for
loop in bash
.
How can one do an equivalent loop in a POSIX shell script?
As there are various ways of achieving the same goal, feel free to add your own answer and elaborate a little on how it works.
An example of one such bash
loop follows:
#!/bin/bash
for (( i=1; i != 10; i++ ))
do
echo "$i"
done
Best Answer
I have found useful information in Shellcheck.net wiki, I quote:
Bash:
POSIX:
though beware that
i++
is not POSIX so would have to be translated, for instance toi += 1
ori = i + 1
.:
is a null command that always has a successful exit code. "$((expression))" is an arithmetic expansion that is being passed as an argument to:
. You can assign to variables or do arithmetic/comparisons in the arithmetic expansion.So the above script in the question can be POSIX-wise re-written using those rules like this:
Though here, you can make it more legible with:
as in
init
, we're assigning a constant value, so we don't need to evaluate an arithmetic expression. Thei != 10
intest
can easily be translated to a[
expression, and fornext
, using a shell variable assignment as opposed to a variable assignment inside an arithmetic expression, lets us get rid of:
and the need for quoting.Beside
i++
->i = i + 1
, there are more translations of ksh/bash-specific constructs that are not POSIX that you might have to do:i=1, j=2
. The,
arithmetic operator is not really POSIX (and conflicts with the decimal separator in some locales with ksh93). You could replace it with another operator like+
as in: "$(((i=1) + (j=2)))"
but usingi=1 j=2
would be a lot more legible.a[0]=1
: no arrays in POSIX shellsi = 2**20
: no power operator in POSIX shell syntax.<<
is supported though so for powers of two, one can usei = 1 << 20
. For other powers, one can resort tobc
:i=$(echo "3 ^ 20" | bc)
i = RANDOM % 3
: not POSIX. The closest in the POSIX toolchest isi=$(awk 'BEGIN{srand(); print int(rand() * 3)}')
.