[Rear-users] Better way to extend arrays in bash (+=)

Schlomo Schapiro schlomo at schapiro.org
Thu Apr 23 12:15:07 CEST 2009


Hi,

while reading the bash manpage I found this little gem:

       A variable may be assigned to by a statement of the form

              name=[value]

       If  value  is  not  given,  the variable is assigned the null
string.  All values undergo tilde expansion,
       parameter and variable expansion, command substitution,
arithmetic  expansion,  and  quote  removal  (see
       EXPANSION below).  If the variable has its integer attribute set,
then value is evaluated as an arithmetic
       expression even if the $((...)) expansion is not used (see
Arithmetic Expansion below).  Word splitting is
       not performed, with the exception of "$@" as explained below
under Special Parameters.  Pathname expansion
       is not performed.  Assignment statements may also appear as
arguments  to  the  alias,  declare,  typeset,
       export, readonly, and local builtin commands.

       In  the context where an assignment statement is assigning a
value to a shell variable or array index, the
       += operator can be used to append to or add to the variable’s
previous value.  When +=  is  applied  to  a
       variable  for which the integer attribute has been set, value is
evaluated as an arithmetic expression and
       added to the variable’s current value, which is also evaluated.
When += is applied to an  array  variable
       using  compound  assignment (see Arrays below), the variable’s
value is not unset (as it is when using =),
       and new values are appended to the array beginning at one greater
than the array’s  maximum  index.   When
       applied to a string-valued variable, value is expanded and
appended to the variable’s value.


Which means that instead of writing tediously

VAR=( "${VAR[@]}" some "more stuff" )

we can now simply write

VAR+=( better "and nicer stuff" )

and make the code look much better:

$ VAR=( first stuff )
$ for v in "${VAR[@]}" ; do echo "$v" ; done
first
stuff
$ VAR=( "${VAR[@]}" some "more stuff" )
$ for v in "${VAR[@]}" ; do echo "$v" ; done
first
stuff
some
more stuff
$ VAR+=( better "and nicer stuff" )
$ for v in "${VAR[@]}" ; do echo "$v" ; done
first
stuff
some
more stuff
better
and nicer stuff

(note how this also preserves the array members with spaces in them!)

I found this in bash 3.2.25. Can you please check with your bash version
and post wether it also works there? Of course only for Kernel 2.6
systems (as that is what ReaR supports).

I would then suggest to migrate to the new form of extending arrays as
it looks better and reduces code complexity. No need to go through all
scripts and change it but I would use it with new code.

Regards,
Schlomo

PS: And those who wonder are encouraged to do man bash :-)

PPS: For those who don't know. ReaR depends on bash version 3 and not on
"sh"! That is why we allow ourselves to use the arrays and other fancy
stuff and MUST use #!/bin/bash instead of #!/bin/sh !




More information about the rear-users mailing list