I should have added in my last reply that if you want to investigate field splitting, and how it works in various cases, use the expansion of a simple variable
x=whatever IFS=something echo $x or better: args() { printf '#=%d' "$#" [ "$#" -gt 0 ] && printf ' <%s>' "$@" printf '\n' } and use "args" instead of echo, it makes things clearer (just don't use < or > in the tests anywhere). Then, once that is fully understood, you can go on to dealing with field split $* and $@ but when you're doing that, don't forget this part of XCU 2.5.2 (describing the '*' special parameter). When the expansion occurs in a context where field splitting will be performed, any empty fields may be discarded That "may" was mentioned before, but it continues: and each of the non-empty fields shall be further split as described in Section 2.6.5. and there note that any empty fields that are not discarded are not subject to field splitting. The reason for that is simple: POSIX describes what the shells actually do, not what would make rational sense, and if empty fields were also to be field split, that "may" just before would turn into a "shall" (regardless of IFS, unless it is empty) which isn't what shells actually do. That's because field splitting requires that any empty resulting word be discarded (regardless of whether the word changed in any way because of the field splitting). That's why, and is the only reason why A= echo $A $A $A $A prints just a newline, not 3 spaces, and then a newline. echo there is (and is required to be) given no args at all. Replace that with set -- '' '' '' '' echo $* and all bets are off, nothing specific is required (except the trailing newline). Any number of spaces, 0..3, is permitted, and what you get depends on what is in IFS even though you'd expect it shouldn't, as there is nothing anywhere to match an IFS character, or not unless you know how an implementation actually implements that, which isn't something any user should be expected to know, and certainly never to depend upon. You have to combine all of that together, and also copy the implementation technique bash uses for unspecified cases, if you really want to generate the same results that bash does. kre ps: to anyone out there still reading this, when writing sh code, don't lapse into writing C instead, in sh, when using quotes, use '' (or \) whenever the quoted text is to be treated literally, and "" only when you are expecting expansions in the included string - doing it the C way ('c' for a single character, and "str" when it is a string) makes no sense in sh at all, in sh everything is a string, quoting is only ever needed to avoid some character(s) from having some other meaning then simply representing themselves (either in sh parsing, or in one of the expansions that happen). Use $'' when you want something that is more or less identical to a C string (including the transformations that C allows inside one, like \n becoming a newline, etc).