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: Andy Chu
Subject: Re: [Help-bash] Awkward behavior of empty arrays
Date: Tue, 5 Sep 2017 09:33:00 -0700

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