help-bash
[Top][All Lists]
Advanced

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

Re: [Help-bash] Awkward behavior of empty arrays


From: Cristian Zoicas
Subject: Re: [Help-bash] Awkward behavior of empty arrays
Date: Thu, 7 Sep 2017 09:07:44 +0200
User-agent: Mozilla/5.0 (X11; Linux i686; rv:43.0) Gecko/20100101 Firefox/43.0 SeaMonkey/2.40



Andy Chu wrote:
Hm, interesting.  I think your whole message below can be rephrased as: empty 
arrays don't work with set -u.  Is that right?

If so I agree, and I would consider that a design problem.I just tested mksh and it 
does the same thing as bash.  (mksh is a pksh fork, and pdksh was a clone of 
AT&T ksh, so I suspect the behavior originated there.)

set -u is useful with arrays for out-of-bounds checks:

$ set -u
$ declare -a A=(1 2 3)
$ echo "${A[2]}"
$ echo "${A[3]}"
-bash: A[3]: unbound variable

But I agree that the empty array check is undesired.  It's also inconsistent 
with the argv array:

$ set -u
$ set --   # clear argv array
$ echo "$#"
0
$ argv "$@"  # gives desired empty array of argument, not error
[]

Horrible workaround:

Copy to the argument array:

set -- "address@hidden"

Copy from the arguments array:

declare -a A=( "$@" )

Then use "$@" , for i in "$@", etc. everywhere?

-----

I would also like it if bash would provide a way to safely interpolate empty 
arrays with set -u.  Syntax idea:

echo "${A[@@]}"

That way there is no extra mode, which is harder to read IMO.


Andy




On Tue, Sep 5, 2017 at 4:02 AM, Cristian Zoicas <address@hidden 
<mailto:address@hidden>> wrote:

    Hello all and sorry for the delay.

    Now after reading the answers from all of you I'll resume next my 
conclusions. Below you may
    find comments related to your previous answer but in order to be short, I 
have addressed
    only problems related to my original question (empty arrays).

    1) @Andy Chu

        > 1. Never use anything that isn't in parentheses on the RHS of an 
array initialization.
        >
        > OK:
        > declare -a A=()
        > decare -a A=(1 2 3)

        While the second stamtement is ok  (I mean, the array works well if I 
want to find
        the number of elements or to  expand it), the first one is problematic.

        Aparently 'declare -a A=()' works. But it works until you try to expand 
"address@hidden".
        Try the following code (essentially my example 2):

        set -u
        unset A
        declare -a A=()
        echo "address@hidden"

        The last statement will give you the error "bash: address@hidden: unbound 
variable".

        So 'declare  -a A=()'  is not  an effective  way of  creating empty 
arrays.
        I would even add that bash does not support empty arrays.

        > INVALID:
        > declare -a A=  (your example 1)
        >
        >
        > The way you should read this is "I'm assigning a string to an array". 
 Bash does the
        > non-obvious thing of coercing the string to an array -- by creating 
an array
        > with ONE element.

        In a  shell context  I could  understand that  such a  statement is 
invalid (if it
        would be impossible or too difficult to implement it in a more  user 
friendly way).
        Normally  I would not use  it, but I had the need of creating an  emtpy 
array, so
        I wrote that statement and in  the end  I had  the surprise  of 
creating  an array
        with a single element initialized with null.

        Bash did the very-non-obvious thing of creating an array with a single 
element from null.

        >
        > 2. Never reference an array with anything but "address@hidden" or 
"${A[i]}" where
        >    i is an integer (double quotes are mandatory in both cases).
        >

        I wouldn't but the manual says

            "When there are no array members, address@hidden expands to 
nothing."

        So "address@hidden" should be different from address@hidden Look at my 
example 1.

        With the statement 'declare -a A=;' I was hoping to create an empty 
array. The  for loop (by
        luck)  did what I expected:  the array did not contain  any elements  
(I thought)  so address@hidden
        (not "address@hidden") expanded to  nothing as  the documentation  says 
and  the statemnts inside
        the loop were not executed.

        On the other side if I would have written the for loop as

           for e in "address@hidden"; do echo "e: ${e}"; done

        the statement "echo" would have been executed.

        The for loop worked because A was created as an array with a single 
null element. And
        the sentence "When there are no array members, address@hidden expands to 
nothing." is the
        manual is wrong. When  an array is empty, it is considered undefined 
(see my example 2).

    2) @Chet Ramey

        > Yes. The manual also says that assigning to an array without using a 
subscript is
        > equivalent to assigning to element 0 (or "0").

        I think that the manual should be more clear about what is going on when
        assigning null to an array when not using the syntax

            name=(value1  ...  valuen)

         If  the  manual says  that  "declare  -a  A=" is  equivalent  with 
assigning  to the
         element 0  then it  should be  included in  the Arrays section.

        > Example 2
        > ...
        >
        > The real question is whether or not the size/length operator should 
error out when there
        > are no elements in the array. The current behavior could be 
considered a bug.
        >

        If the  current behavior could  be considered  a bug then  it means 
that bash does not support
        empty  arrays. Or that bash support them in a very restricted way, that 
is  only to create
        them, but not to use them.

        This is also in contradiction with the manual statement "When there are no 
array members, address@hidden expands to nothing."


    In my opinion bash should support

        a) *real*  arrays. we  should have  the possibility  of iterating
           over   arrays  elements  even  if the  arrays  are  empty  or
           not. Currently that is not supported.

        b) the possibility  of expanding an array to the  set of string
           stored in its elements and if  the array is empty then we must
           get an empty set of strings.

    regards
    Cristian Zoicas







reply via email to

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