Robert Elz wrote in
<[email protected]>:
|I should have added in my last reply that if you want to investigate
Before i apologise to Greg Wooledge i want to point out that POSIX
says:
* Expands to the positional parameters, starting from one,
initially producing one field for each positional parameter that
is set. When the expansion occurs in a context where field
splitting will be performed, any empty fields may be discarded
and each of the non-empty fields shall be further split as
described in Section 2.6.5.
By the very meaning of this the fields are split individually,
*first*. This is exactly what i do.
Hence
echo $#,1="$1"/$1,2="$2"/$2,3="$3"/$3,4="$4"
->
4,1=:a:/ a ,2=a/a,3=/,4=a
becomes
:a: -> '' + a
a -> a
'' -> discarded (but remembered as it separates fields)
a -> a
becomes, with IFS=:, when actually creating the argument
:a:a::a
becomes the actual argument
< a a a>
Like is said, in a sh(1) script
a() {
echo $#,1="$1"/$1,2="$2"/$2,3="$3"/$3,4="$4"
echo $#,'*'="$*"/$*,
}
set -- '' 'a' ''
for f in ' ' '' : ': ' ' :'; do
IFS=$f ; echo "$*"$* $*; a "$*"$* $*;unset IFS
done
the difference in between the shells and my shell expression thing
--- .1 2025-03-15 23:38:31.359307576 +0100
+++ .2 2025-03-15 23:38:32.715974215 +0100
@@ -6,10 +6,10 @@ a a a$
3,*=aaa/a a a,$
:a: a a$
4,1=:a:/ a ,2=a/a,3=/,4=a$
-4,*=:a::a::a/ a a a,$
+4,*=:a::a::a/ a a a,$
:a: a a$
4,1=:a:/ a ,2=a/a,3=/,4=a$
-4,*=:a::a::a/ a a a,$
+4,*=:a::a::a/ a a a,$
a a a$
3,1= a / a ,2=a/a,3=a/a,4=$
3,*= a a a/ a a a,$
|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).
--End of <[email protected]>
--steffen
|
|Der Kragenbaer, The moon bear,
|der holt sich munter he cheerfully and one by one
|einen nach dem anderen runter wa.ks himself off
|(By Robert Gernhardt)