On Fri, Aug 23, 2024 at 01:28:49 +0200, Steffen Nurpmeso wrote: > a() { echo $#,1=$1,2=$2,"$*",$*,; } > set -- a b c > echo 2 > IFS=:; echo "$*"$*; a $* "$*";
Your printing function "a" is highly questionable. It's got unquoted word expansions that'll do who knows what, and it's also using echo which may interpret contents and alter them. If you want to see the arguments given, I recommend this instead (assuming bash): args() { if (($#)); then printf '%d args:' "$#" printf ' <%s>' "$@" echo else echo "0 args" fi } If you need it to work in sh, replace (($#)) with something like test "$#" != 0. You could also write a script named args which performs the same steps, so that it can be invoked from anywhere. Here's mine: hobbit:~$ cat bin/args #!/bin/sh printf "%d args:" "$#" test "$#" -gt 0 && printf " <%s>" "$@" echo > Why does bash (aka sh(1)) word splits > > IFS=:; echo "$*"$*; a $* "$*"; > ^ > this > > unquoted $* at SPACE into three different tokens? Unquoted $* is expanded in three passes. The first pass generates one word per parameter. The second pass applies word-splitting (based on IFS) to each word. The third pass applies globbing (pathname expansion) to each of *those* words. So, you're expanding $* to <a> <b> <c>. Since none of those words contains any IFS characters, or any globbing characters, that's the final list. You're therefore calling a with 4 parameters: a "a" "b" "c" "a:b:c" > then bash gives me > > 2 > a:b:ca b c > 4,1=a,2=b,a:b:c:a:b:c,a b c a b c, Your printing function contains an unquoted $*, so we repeat the same procedure. You have 4 parameters, so $* is first expanded to a list of one word per parameter: <a> <b> <c> <a:b:c>. Next, since IFS is set to : at this point, the fourth word is split into a new list of words, and now you have <a> <b> <c> <a> <b> <c>. Finally, globbing would apply. In this case, there are no globbing characters, so no further changes occur. Ultimately, you call echo with the following arguments: echo "4,1=a,2=b,a:b:c:a:b:c,a" "b" "c" "a" "b" "c," echo doesn't care about IFS, so it writes these arguments with spaces between them, and therefore you see the output that you see. Unquoted $* and $@ are almost always errors. You should not use them without an extremely good reason. In 90% of cases, what you want is "$@" which preserves the parameter list. In 9% of cases, you want "$*" which concatenates all the parameters together into a single string, for reporting.