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

Rob Landley rob at landley.net
Fri Mar 6 15:46:37 PST 2020


> 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:

$ bash -c 'IFS=xy; for i in axb$@$@cyd; do echo =$i=; done' one "" abc dxf ghi
=a b=
=abc=
=d=
=f=
=ghi=
=abc=
=d=
=f=
=ghic d=

vs

$ bash -c 'IFS=xy; for i in axb$@$@cyd; do echo =$i=; done' one f "" abc dxf ghi
=a bf=
==
=abc=
=d=
=f=
=ghif=
==
=abc=
=d=
=f=
=ghic d=

(Yes, the x and y in the bracketing material become spaces, but the x and y in
the variable expansions become word breaks. That's not the weird part.)

The WEIRD part is that last message happily took two consecutive empty arguments
and output ONE of them. And there's no obvious way to know _which_ one....
except maybe:

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

It's the first one that's kept. I have no idea what the reasoning here is. It
would be refreshing if there was some.

Rob

P.S. This is why I describe my coding style as "debugging an empty screen"...


More information about the Toybox mailing list