[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Question on $IFS related differences (Was: Question on $@ vs $@$@)
From: |
Steffen Nurpmeso |
Subject: |
Re: Question on $IFS related differences (Was: Question on $@ vs $@$@) |
Date: |
Wed, 18 Sep 2024 23:34:14 +0200 |
User-agent: |
s-nail v14.9.25-608-ge479530e8d |
Robert Elz wrote in
<3946.1726671659@jacaranda.noi.kre.to>:
...
|| On Wed, Sep 18, 2024 at 08:05:10 +0300, Oğuz wrote:
||> It boils down to this:
||> f(){ echo $#;}; set "" "" ""; IFS=x; f $*
|
||> bash, NetBSD and FreeBSD sh, and ksh88 all agree and print 2. pdksh
||> prints 3 but mksh and oksh print 1. dash, ksh93, yash, and zsh print
||> 0.
|
|There is no right answer there, 0 and 3 are the most likely results, but
|1 and 2 are also possible.
...
|And for the example from Oğuz, the value of IFS should be completely
|irrelevant, as there's nothing anywhere in that example which actually
And yet it is not for the shells.
|needs splitting. The expansion of $* (unquoted, in a context where
|field splitting occurs) is supposed to produce 3 fields (since there are
|3 set numeric parameters) each of which contains nothing ("") - each of
|those is then subject to field splitting, but when there's nothing, there's
|nothing.
|
|The standard says that "any empty fields may be discarded" (that's
|actually before the field splitting is to happen, but here it makes no
|difference). Note the "any ... may", so the implementation is allowed
|to, but not required to, discard any of the three empty fields that
|have been produced. So it can discard none, (answer 3) or discard all
|of them (answer 0) which are the more reasonable choices, or it can
|discard 1 (answer 2) or 2 (answer 1) of the three. Any of those is \
|possible.
And then Oğuz simply stops on the way, because if i modify my own
thing to
a() {
echo $#,1=$1,2=$2,3=$3,4=$4,5=$5,6=$6,"$*",$*,
}
set -- '' 'a' ''
IFS=':'; a $*
IFS=' '; a $*
then not "all agree" and i get
#?0|kent:tmp$ bash t.sh
2,1=,2=a,3=,4=,5=,6=,:a, a,
1,1=a,2=,3=,4=,5=,6=,a,a,
#?0|kent:tmp$ dash t.sh
1,1=a,2=,3=,4=,5=,6=,a,a,
1,1=a,2=,3=,4=,5=,6=,a,a,
#?0|kent:tmp$ busybox.static sh t.sh
1,1=a,2=,3=,4=,5=,6=,a,a,
1,1=a,2=,3=,4=,5=,6=,a,a,
#?0|kent:tmp$ ...
3,1=,2=a,3=,4=,5=,6=,:a:, a ,
1,1=a,2=,3=,4=,5=,6=,a,a,
|| Please don't do this in your scripts.
...
|Here, as best I can tell, none do - though I know that the shell I
|maintain (the NetBSD sh) gets to this point more by a fluke than
|anything else, treating the $* as if it were "$*" - except unquoted
|and thus subject to field splitting (perhaps bash does the same thing).
|
|Then the expansion of $* above gives xx (not nothing) which is then
|field split, which produces 2 fields (as each x is really a field termin\
|ator,
|no field follows the final one). It doesn't matter what IFS[0] is for
|this, as long as it isn't white space, the same result will always happen
|(the expansion inserts it, field splitting removes it). When IFS[0] is
|white space, different rules apply to the field splitting algorithm, which
|is why the results differ in that case.
'still trying to align my head with 2.6.5 field splitting, but it
seems a matter of "delimination" or not
At this point, if the candidate is not empty, or if a sequence
of bytes representing an IFS character that is not IFS white
space was seen at step 4, then a field is said to have been
delimited, and the candidate shall become an output field.
|Nothing allows empty fields produced by field splitting to be discarded,
|so we end up with 2 fields remaining.
|
|How 0 or 3 are produced is easy to see (either all, or none, of the empty
|fields are discarded, either of which is a reasonable choice) - then field
|splitting would happen on the ones not discarded, but cannot split anything
|when the fields are empty.
|
|I'm not sure what the implementation mechanics are which would actually
|produce 1 field as the result.
|
|
|So Steffen, if you were writing a shell, then you could do whatever you
|like in this case, the value of IFS really should not matter at all, and
|either 0 or 3 fields are sensible answers. For a MUA, I think you get
|to do whatever you like, and trying to copy the various bizarre shell
|behaviour in this case (that different shells implement this differently
|is why the standard is so vague about what happens) doesn't make much \
|sense.
It seems so, dear Robert. But logically derivable it should be,
and thus i am thankful for the efforts of yours.
|And certainly, if you're writing a script, just don't do things like this.
Field splitting seems to be a fragile concept. Even though
i "use" the shell for the quarter of a century, and use it for
a bit more than "just maintainance scripting" for way over
a decade, the fact that anything but "$@" is nothing but
non-portable and very fragile yet escaped me.
--End of <3946.1726671659@jacaranda.noi.kre.to>
Thank you, and
Ciao!
--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)
- Question on $IFS related differences (Was: Question on $@ vs $@$@), Steffen Nurpmeso, 2024/09/17
- Re: Question on $IFS related differences (Was: Question on $@ vs $@$@), Oğuz, 2024/09/18
- Re: Question on $IFS related differences (Was: Question on $@ vs $@$@), Greg Wooledge, 2024/09/18
- Re: Question on $IFS related differences (Was: Question on $@ vs $@$@), Chet Ramey, 2024/09/18
- Re: Question on $IFS related differences (Was: Question on $@ vs $@$@), Robert Elz, 2024/09/18
- Re: Question on $IFS related differences (Was: Question on $@ vs $@$@),
Steffen Nurpmeso <=
- Re: Question on $IFS related differences (Was: Question on $@ vs $@$@), Steffen Nurpmeso, 2024/09/18
- Re: Question on $IFS related differences (Was: Question on $@ vs $@$@), Robert Elz, 2024/09/18