bug-bash
[Top][All Lists]
Advanced

[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)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]