Bourne | Ash |  #!  | find | ARG_MAX | Shells | whatshell | 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.

2011-03-12 (see recent changes)

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

The actual behaviour varies among different shells.
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 underscores to make reading easy.

The second table at the right illustrates another issue: how is splitting with set influenced by IFS? (commas mean separated values)

Shell default IFS [2] unset [3]
like default?
IFS=x IFS= IFS='\'
 $*   $@  "$*" "$@"  $*   $@  "$*" "$@"  $*   $@  "$*" "$@"  $*   $@  "$*" "$@"
V7 ... SVR4.2 ._. ._. ._. ._. error ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._.
bash-1.05 ._. ._. ._. ._. error ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._.
bash-1.14.0,1.14.7 ._. ._. ._. ._. error ._. ._. .x. ._. ._. ._. .. ._. ._. ._. .\. ._.
traditional ash ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._. ._.
recent ash ._. ._. ._. ._. .x. .x. .x. .x. .. .. .. .. .\. .\. .\. .\.
ksh86 ._. ._. ._. ._. like IFS= .x. .x. .x. .x. ._. ._. .. ._. .. .. .\. .\.
ksh88-d, g, h, i ._. ._. ._. ._. .x. .x. .x. .x. ._. ._. .. ._. .. .. .\. .\.
bash-2.00, -2.04 ._. ._. ._. ._. ._. ._. .x. ._. ._. ._. .. ._. ._. ._. .\. ._.
bash-2.05, -3.0.0 ._. ._. ._. ._. .x. ._. .x. ._. ._. ._. .. ._. .\. ._. .\. ._.
bash-3.1.0, -4.2.0 ._. ._. ._. ._. .x. ._. .x. ._. .. ._. .. ._. .\. ._. .\. ._.
ksh93-d,e,q ._. ._. ._. ._. .x. ._. .x. ._. .. ._. .. ._. .\. ._. .\. ._.
pdksh-5.2.14 ._. ._. ._. ._. .x. .x. .x. .x. ._. ._. .. ._. .\. .\. .\. .\.
posh-0.5.4/-0.8.5 ._. ._. ._. ._. .x. .x. .x. .x. ._. ._. .. ._. .\. .\. .\. .\.
mksh-R28, -R39 ._. ._. ._. ._. .x. .x. .x. .x. ._. ._. .. ._. .\. .\. .\. .\.
zsh/sh-3.0.8, 4.1.1 ._. ._. ._. ._. SEGV [4] .x. .x. .x. .x. .. .. .. .. .\. .\. .\. .\.
zsh/sh-4.2.5 ._. ._. ._. ._. .x. .x. .x. .x. .. .. .. .. .\. .\. .\. .\.
 
SUSv3 sh [5] ? ? ._. ? ? ? .x. ? ? ? .. ? ? ? .\. ?
x=:a:b:: IFS=:  
 
set $x  
a,b
a_b
,a,b,
,a,b,,
,a,b,
,a,b,
,a,b,
,a,b,
,a,b,
,a,b,
,a,b,
,a,b,
,a,b,, / ,a,b,
,a,b,
:a:b:: / ,a,b,,
:a:b:: / ,a,b,,
 
?

[2] The default IFS is ' \t\n' (space tabulator newline).
zsh comes with an additional null byte ' \t\n\0'.
[3] Originally, it was not possible to unset IFS. Modern shells allow this and the behaviour
should be as if IFS was set to the default. The column list exceptions.
[4] The SEGV occurs 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), UnixWare 7.1.4 (ksh88-g, M-ksh88-h), SunO 5.9 (M-ksh88-i)
ksh93: UnixWare 7.1.4 (M-ksh93-d, ksh93-e), SunOS 5.9 (M-ksh93-d), Linux (ksh93-q)
zsh-3.0.8: SunOS 5.9

[endnote] 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.

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, both VAR and y are exported.
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.

See also Stéphane Chazelas remarks about IFS handling.


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