bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: change in behavior starting with bash-4.3_p14 and $@ in [[...]]


From: Chet Ramey
Subject: Re: change in behavior starting with bash-4.3_p14 and $@ in [[...]]
Date: Wed, 13 Aug 2014 15:59:45 -0400
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:24.0) Gecko/20100101 Thunderbird/24.6.0

On 8/13/14, 10:09 AM, Greg Wooledge wrote:
> On Wed, Aug 13, 2014 at 09:47:51AM -0400, Chet Ramey wrote:
>> On 8/12/14, 11:05 PM, Mike Frysinger wrote:
>>> foo=(0 0 0); [[ -z ${foo[@]#0} ]]; echo $?
> 
>> Word splitting is
>> suppressed inside [[, so the array expands to a single word ("0 0 0"), the
>> 0s are removed, leaving "  "
> 
> That doesn't sound right.  Either you get a single word and remove the
> leading 0 only, or you remove the 0s from each array element first,
> and then get a single word by concatenating what's left.

Not quite.  The expansion happens before word splitting, and the @ causes
the result to be treated specially.  This is the basic set of steps:

1.  The foo[@] is expanded into a list (0 0 0), noting that the @ was
    present so the result can be handled accordingly.

2.  The #0 is applied to each member of the list, as it would be in any
    other context.  If you were to echo the results here, kind of like
    you did below, you would get three empty words.

3.  The results are `glued' together as if $* were used, due to the
    presence of `@', so the three empty words are separated by two spaces.

4.  The two spaces remain because word splitting is not performed; the
    empty words disappear.

> The code that Mike posted is pretty wonky in the first place.  I don't
> understand what its intent is.  (It's expanding an array into a list of
> words in a context where you can't have a list... and then checking the
> string length of that list-not-list as if it were a string... what?)

Yeah, I assume it's a quick way to test whether all elements of an array
are identical.

> 
> The right-hand side of an assignment also suppresses word splitting, so
> I tried this:
> 
> imadev:~$ foo=(0 0 0); x=${foo[@]#0}
> imadev:~$ echo "<$x>"
> <>
> imadev:~$ foo=(0 0 0); x="${foo[@]#0}"
> imadev:~$ echo "<$x>"
> <  >
> imadev:~$ echo $BASH_VERSION
> 4.3.22(5)-release
> 
> Looks like the second one expanded to a list of empty words and then
> concatenated them together with spaces.  I have no idea what the first
> one did, or why it's different.

It looks like a bug.  I assume it's because bash treats "$@" and $@
(and their array equivalents) differently, even in contexts where word
splitting is not going to happen.  I will have to look at it.

Chet

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRU    chet@case.edu    http://cnswww.cns.cwru.edu/~chet/



reply via email to

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