[Toybox] Would someone please explain what bash is doing here?

Rob Landley rob at landley.net
Fri Mar 6 18:05:37 PST 2020


On 3/6/20 5:46 PM, Rob Landley wrote:
>> On Fri, Mar 6, 2020 at 4:03 AM Rob Landley <rob at landley.net> wrote:
>>>
>>> Is it just me, or is bash's unquoted $@ processing with a non-whitespace IFS
>>> only retaining blank arguments when they're followed by another argument (even
>>> if that one is blank)?
>>>
>>> $ func() { bash -c 'IFS=x; for i in $@; do echo =$i=; done' blah "$@"; }
>>> $ func one "" two
>>> =one=
>>> ==
>>> =two=
>>> $ func one ""
>>> =one=
>>> $ func "" two
>>> ==
>>> =two=
>>> $ func "" ""
>>> ==
>>>
>>> (I mean, it could be worse. Busybox ash is _never_ retaining zero length
>>> arguments here. But I'm trying to figure out what logic bash is using, and not
>>> finding a coherent design idea. Is this a bug, or did they mean to do it? If
>>> they meant it, _why_?)
>>>
>>> Rob
>>>
>>> P.S. I dug up bash 2.05b and at least it's been CONSISTENT for 18 years, so I
>>> guess that's something? But... why?
>>>
>>> P.P.S. As far as I can tell, $@ and $* behave the same unquoted, and that's the
>>> codepath I'm currently trying to implement.
>>
>> On 3/6/20 10:08 AM, enh wrote:
>>
>> you could try chet ramey or the bash mailing list... he joins in a lot
>> of the shell discussions on the POSIX mailing list.
> 
> I'm reluctant to trigger a change in bash's behavior that it's been doing
> consistently since at least 2002, but I am curious WHY it's doing this.
> 
> It's start _or_ end of the list that the empty argument drops out, by the way:

Nevermind, I think I've figured most of it out. The leading/trailing part is
because:

bash -c 'IFS=xy; for i in axyxb$@$@cyd; do IFS=z; echo =$i=; done' \
  one "" abc dxf ghi

The echo expansion is ALSO getting split.

I'm currently trying to figure out why:

$ bash -c 'IFS=xy; for i in axyxb$@; do echo =$i=; done' one f "" abc
=a   bf=
==
=abc=

is producing THREE spaces, but mine is doing:

=a  bf=
==
=abc=

It turns into echo "=a" "" "bf=" and when I do that from the command line I get
a space before and a space after the NULL argument? But with bash there are
three? Is it turning into two NULL entries? Ah, it SHOULD do that because there
are two consecutive non-whitespace IFS separators that don't bind to an existing
string (like the first one does). So why _isn't_ mine doing that...

(This is why I mostly blog about this stuff instead of posting it here. I am SO
deep in the weeds that I just looked up Seanan McGuire's phrase "The turtle
couldn't help us" and found out it's a Steven King reference...)

Rob


More information about the Toybox mailing list