I’ve read some of the related questions on the subject but didn’t find the precise one I have in mind. I hope it’s not because it is too stupid.
In Bash 5 (5.2.15 if that matters), does it make any difference declaring an array like:
declare -a foo
compared with:
declare -a foo=()
I wonder if the first declaration does ensure the creation of an empty array, or only the second one guarantees that?
You may ask, what the point in initializing an empty array? Why not initializing it only when it’s needed storing a first element?
Well, I don’t know, maybe?
Then another question arises, would it be safe to initialize the array only when storing the first element with the append operator? Like:
bar+=('baz')
(bar here being not defined before this first element is appended)
it seems not to be a problem, even if option nounset is set, but doing so, am I assured 'baz' will always be the first element in the array? Is it safe to do that?
Also, in the case I’d need to change the default scope of the variable, I guess I couldn’t avoid using declare
(or local
), and it seems wrong to call declare or local every times I append an element (while it seems to work though).
Sorry if it’s a stupid question or is badly worded.
Have a nice day.
Addressing the declare -a foo
vs declare -a foo=()
(vs foo=()
) question ...
The results are going to depend on what's in foo
prior to the declare -a
.
$ foo=a # set to single character
$ declare -p foo
declare -- foo="a"
$ declare -a foo # convert to array
$ declare -p foo
declare -a foo=([0]="a") # maintains initial value of 'a'
---------------------------------
$ foo=a # set to single character
$ declare -p foo
declare -- foo="a"
$ declare -a foo=() # convert to array but also clear contents
$ declare -p foo
declare -a foo=() # array is empty
---------------------------------
$ foo=(a b c) # set to 3 element array
$ declare -p foo
declare -a foo=([0]="a" [1]="b" [2]="c")
$ declare -a foo # (re)declare as array
$ declare -p foo
declare -a foo=([0]="a" [1]="b" [2]="c") # maintains intitial set of 3 values
---------------------------------
$ foo=(a b c) # set to 3 element array
$ declare -p foo
declare -a foo=([0]="a" [1]="b" [2]="c")
$ declare -a foo=() # (re)declare as array but also clear contents
$ declare -p foo
declare -a foo=() # array is empty
Findings:
foo
is undefined then declare -a foo
, declare -a foo=()
and foo=()
behave the samefoo
is predefined then declare -a foo
will maintain the predefined value, while declare -a foo=()
and foo=()
will clear the contents of foo
If you know with 100% certainty your variable (foo
in this case) is undefined then you're safe with declare -a foo
or declare -a foo=()
or foo=()
.
If you're not sure about the contents of the variable (eg, it was exported by the parent process) then you're safer explicitly clearing the variable with declare -a foo=()
or foo=()
.
If you need the array to be empty then I'd suggest always explicitly defining the array as empty via declare -a foo=()
or foo=()
.
NOTES:
foo
and then try to define as an associative array (declare -A foo
)unset foo
as this eliminates any unwanted leftover behavior from other declare
flags (eg, -x
, -r
, etc), and then declare
and populate the variablefoo=(a b c); declare -A foo
you'll generate an error since bash
won't convert an 'indexed' array to an associative array ... a good example where unset foo
should be run before creating/populating (a new) foo