Pick at least 4 operations that you can do in bashisms-free shell scripts:
$((n+1)) $((n>8)) $((n^4)) $((--n)) $((n*=5)) $((n++)) $((n==1?2:3))
The POSIX:2001 standard defines the arithmetic expansion requirements, which leads us to selecting all of the above operations except two:
$((--n)) $((n++))
"--" and "++" are not required to be implemented, and in some cases they may lead to unexpected results, such as the following:
$ bash -c 'n=1; echo $((++n))'
2
$ dash -c 'n=1; echo $((++n))'
1
Remember, if you rely on any non-standard behaviour or feature make sure you document it and, if feasible, check for it at run-time.
Additional fun:
ReplyDeletePOSIX says to use the host’s “long” C type. This means that $((2147483647+1)) is 2147483648 on a 64-bit (or 36-bit) system and Undefined Behaviour on a 32-bit (or 31-bit) system.
ISO C “Undefined Behaviour” (yes, capitalised) is pretty bad. The C compiler is allowed to compile the C source code of the shell in a way so that “echo $((2147483647+1))” equals “rm -rf ~ /”, no kidding.
mksh is saner, but incompatible with POSIX there, since it behaves the same across *all* platforms: $((2147483647+1)) is -2147483648 on mksh, everywhere (defined signed 32-bit wraparound). If you need POSIX behaviour with mksh, use the “lksh” binary shipped as part of the Debian package; it’s also used for /bin/sh in jessie/sid if you choose to use mksh instead of GNU bash or dash. (mksh also supports more stuff than POSIX, like unsigned arithmetics, rotation left/right, etc.)
Additionally, POSIX shell arithmetics are a very recent feature and thus not ubiquitous, even on POSIX conformant systems (that conform to older versions of the spec)…
As usual: check and document what you use. If you use shell-specific things, a shebang like #!/bin/mksh does not go amiss. I personally would rather keep my shell portable than my shell scripts…
The 2001 POSIX standard was superseded long ago by the 2008 edition. You can get access via http://www.unix.org/online.html
ReplyDelete@mirabilos POSIX shell arithmetic is not a recent requirement; it was in the original 1992 POSIX.2 shell and utilities standard.
Sure, there is a more recent version of POSIX but it is a specification that is not really followed by the common shell implementations.
Delete