Bourne | Ash |  #!  | find | ARG_MAX | Shells | portability | permissions | UUOC | ancient | - | ../Various | HOME
"$@" | echo/printf | set -e | test | tty defs | tty chars | $() vs ) | IFS | using siginfo | nanosleep | line charset | locale


IFS handling in various shells concerning $* and $@

This page doesn't serve any special purpose, it's just about subtle differences in IFS implementations (and there are numerous such differences).

2009-12-20 (see recent changes)

A variable assignment is not subject to word splitting, no matter what IFS is used. 1
However: the variables $* and $@ are special.

The following results have been collected like this:

    set . . ; IFS='x'
    var=$*;   printf '%s '  "$var"
    var=$@;   printf '%s '  "$var"
    var="$*"; printf '%s '  "$var"
    var="$@"; printf '%s\n' "$var"

Blanks are substituted with an underscore for readability.

Shell default IFS unset [3] IFS=x IFS= IFS='\' IFS=' x'
 $*   $@  "$*" "$@"  $*   $@  "$*" "$@"  $*   $@  "$*" "$@"  $*   $@  "$*" "$@"  $*   $@  "$*" "$@"
V7 ... SVR4 ._. ._. ._. ._. error ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._.
traditional ash ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._.
recent ash ._. ._. ._. ._. .x. .x. .x. .x. .. .. .. .. .\. .\. .\. .\. ._. ._. ._. ._.
ksh86 ._. ._. ._. ._. like IFS= .x. .x. .x. .x. ._. ._. .. ._. .. .. .\. .\. ._. ._. ._. ._.
ksh88-d, 88-Mi ._. ._. ._. ._. .x. .x. .x. .x. ._. ._. .. ._. .. .. .\. .\. ._. ._. ._. ._.
bash-1.14.7 ._. ._. ._. ._. error ._. ._. .x. ._. ._. ._. .. ._. ._. ._. .\. ._. ._. ._. ._. ._.
bash-2.00, -2.04 ._. ._. ._. ._. ._. ._. .x. ._. ._. ._. .. ._. ._. ._. .\. ._. ._. ._. ._. ._.
bash-2.05, -3.0.0 ._. ._. ._. ._. .x. ._. .x. ._. ._. ._. .. ._. .\. ._. .\. ._. ._. ._. ._. ._.
bash-3.1.0, -4.0.35 ._. ._. ._. ._. .x. ._. .x. ._. .. ._. .. ._. .\. ._. .\. ._. ._. ._. ._. ._.
ksh93-d, -q ._. ._. ._. ._. .x. ._. .x. ._. .. ._. .. ._. .\. ._. .\. ._. ._. ._. ._. ._.
pdksh-5.2.14 ._. ._. ._. ._. .x. .x. .x. .x. ._. ._. .. ._. .\. .\. .\. .\. ._. ._. ._. ._.
posh-0.5.4 ._. ._. ._. ._. .x. .x. .x. .x. ._. ._. .. ._. .\. .\. .\. .\. ._. ._. ._. ._.
mksh-R28, -R39 ._. ._. ._. ._. .x. .x. .x. .x. ._. ._. .. ._. .\. .\. .\. .\. ._. ._. ._. ._.
zsh-3.0.8, 4.1.1 ._. ._. ._. ._. SEGV [4] .x. .x. .x. .x. .. .. .. .. .\. .\. .\. .\. ._. ._. ._. ._.
zsh-4.2.5 ._. ._. ._. ._. .x. .x. .x. .x. .. .. .. .. .\. .\. .\. .\. ._. ._. ._. ._.
SUSv3 sh [5] ? ? ._. ? ? ? .x. ? ? ? .. ? ? ? .\. ? ? ? ? ?

[3] Originally, it was not possible to unset IFS. In all modern shells it's possible and the behaviour should be as if IFS was set to the default.
[4] This happens at least in a script expanding "$*".
zsh-4.1.1 is the last version with this bug.
[5] Columns with questionmark: not specified for the SUSv3 shell.

traditional ash:   original Almquist shell, BSDi/OS 4.2, Minix 3.1.1, NetBSD-1.2
recent ash: NetBSD 1.3, and thus all debian ash, FreeBSD 3.1
ksh88: HP-UX 11 (ksh88-c), AIX 3.2 (ksh88-d), SunO 5.9 (M-ksh88-i)
zsh-3.0.8: SunOS 5.9

[1] There's also no pathname expansion in assignments.

Another place where Bourne and bourne-compatible shells don't apply expansions is: "case $variable in [...] "
The reason is probably to be syntactically robust about the content of the variable.

Also, the traditional variants of Bourne and Almquist shell don't apply expansions after redirection operators: "echo text >a*"

There's a divergence with the export built-in:
  VALUE='x y'; export VAR=$VALUE
This results either in export VAR='x y' or export VAR=x y (that is, y is exported, too)
The former applies to ksh88, ksh93, bash-1/2/3/4, pdksh-5.2.14 and mksh-R28/R39.
The latter applies to the original ash, its descendants, posh-0.5.4 and POSIX.
POSIX requires this to be handled as special builtin and not assignment.


<http://www.in-ulm.de/~mascheck/various/ifs/>