[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: |
Thu, 31 Aug 2017 02:51:58 -0700 |
The problems you point out are indeed subtle, but if you follow a few
rules, you can avoid them:
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)
INVALID:
declare -a A= (your example 1)
declare -a A=''
declare -a A='x'
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.
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).
Examples 2 and 3 break this rule -- address@hidden doesn't have double quotes.
also invalid:
"${A}" # this is an implicit "address@hidden" but is confusing
"${A[*]}"
${A[*]}
address@hidden
3. Don't do anything with arrays except COPY them and SPLICE them into
commands.
See my post for the correct ways to do these two things: "Thirteen
Incorrect Ways and Two Awkward Ways to Use Arrays"
http://www.oilshell.org/blog/2016/11/06.html
In particular, don't expect to compare arrays with [[.
$ declare -a A=(A B C D)
$ declare -a B=('A B' 'C D')
$ echo "address@hidden"
4
$ echo "address@hidden"
2
# arrays compare equal because they're coerced to strings before comparison
$ [[ "address@hidden" == "address@hidden" ]]; echo $?
0
I would say that bash also only has "half an array type". Bash will coerce
arrays to strings, and strings to arrays, seemingly at random. It tries
its best to do conversions for you, which is not how any other programming
language with arrays works. (Although this behavior may have originated
with ksh.)
In fact I was thinking of creating a style guide or mode for my
bash-compatible shell OSH to enforce these rules.
The way you would join or split arrays would be:
declare -a myarray=(a b c)
address@hidden # join array into string, no quotes
declare mystr='a b c'
declare -a myarray=( $mystr ) # split mystr into myarray, no quotes
ANY OTHER usage where bash does an implicit conversion would be a fatal
runtime error (if this mode is set). For example, [[ "address@hidden" ==
"address@hidden" ]] would be a fatal runtime error.
You could call this subset of bash the "strict array style" or "hygienic
array style", which I believe is what you're asking for. It's a set of
rules that let you use arrays in the natural manner, with strict errors.
Andy
On Thu, Aug 31, 2017 at 1:38 AM, Cristian Zoicas <address@hidden>
wrote:
>
> Hello all
>
> I want to create arrays and use them (easily). I am especially
> interested in empty arrays and I felt very uncomfortable with them
> since I found some counterintuitive or undocumented behaviors. I
> provide some examples below.
>
> Example 1:
>
> 1 set -u;
> 2 unset A;
> 3 declare -a A=;
> 4 echo "s1";
> 5 echo "size: address@hidden";
> 6 echo "s2";
> 7 for e in address@hidden; do echo "e: ${e}"; done
>
> Starting with the line 3 I want to create an empty array, so I
> declare A to have the array attribute and then I (hope to) assign
> null to it. Some people may say that I am not right because the
> manual says "An array variable is considered set if a subscript
> has been assigned a value." They are somehow right because I did
> not assign any value to any subscript, so the array should not be
> initialized. However let's see what is going on.
>
> Even if I did not assign any subscript a value, the line 5 says
> that the size of the array is 1 and it is possible to reference
> element ${A[0]} without receiving any error due to "set -u". Also
> address@hidden expands to nothing.
>
> If the manual is right, then the array should not be defined. It
> should not exist and I should receive errors due to 'set -u', but
> even 'declare -p A' shows that the array exists and it has a
> single element whose value is null.
>
> Is this behavior of assigning null to an array an to have an array
> with a single null element the desired behavior?
>
> Example 2:
>
> 1 set -u;
> 2 unset A;
> 3 declare -a A=();
> 4 echo "s1";
> 5 echo "size: address@hidden";
> 6 echo "s2";
> 7 for e in address@hidden; do echo "e: $e"; done
>
> Starting with the line 3 I want to create an empty array, so I
> declare A to have the array attribute and then I (hope to) assign
> an empty array to it.
>
> The line 5 behaves well and says that the size of the array is 0,
> thus I imagine that the array is empty. So according to the manual
> address@hidden should expand to nothing and the for loop in the line 7
> should not print anything. Instead the message 'bash: address@hidden:
> unbound
> variable' is printed. As if A is not set.
>
> There is nothing in the manual that says that the () cannot be used
> to create empty arrays. The syntax is also accepted
>
> It means that if the size of the array is 0 then the array cannot
> be expanded. Otherwise it can. Such behavior forces people to
> write difficult to understand/maintain code.
>
> Example 3:
>
> 1 set -u;
> 2 unset A;
> 3 declare -a A=(1); unset A[0];
> 4 echo "s1";
> 5 echo "size: address@hidden";
> 6 echo "s2";
> 7 for e in address@hidden; do echo "e: $e"; done
>
> The behavior of this example is similar with the behavior of the
> example 2 above.
>
> I would like to know if these behaviour make sense.
>
> regards
> Cristian
>
>
>
>
>
>
>
>
>
- [Help-bash] Awkward behavior of empty arrays, Cristian Zoicas, 2017/08/31
- Re: [Help-bash] Awkward behavior of empty arrays,
Andy Chu <=
- Re: [Help-bash] Awkward behavior of empty arrays, Greg Wooledge, 2017/08/31
- Re: [Help-bash] Awkward behavior of empty arrays, Chet Ramey, 2017/08/31
- Re: [Help-bash] Awkward behavior of empty arrays, Andy Chu, 2017/08/31
- Re: [Help-bash] Awkward behavior of empty arrays, DJ Mills, 2017/08/31
- Re: [Help-bash] Awkward behavior of empty arrays, Andy Chu, 2017/08/31
- Re: [Help-bash] Awkward behavior of empty arrays, Greg Wooledge, 2017/08/31
- Re: [Help-bash] Awkward behavior of empty arrays, Chet Ramey, 2017/08/31