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