Is there a way to do something like PHPs $array[] = 'foo';
in bash vs doing:
array[0]='foo'
array[1]='bar'
Yes there is:
ARRAY=()
ARRAY+=('foo')
ARRAY+=('bar')
In the context where an assignment statement is assigning a value to a shell variable or array index (see Arrays), the ‘+=’ operator can be used to append to or add to the variable's previous value.
Also:
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 (for indexed arrays)
As Dumb Guy points out, it's important to note whether the array starts at zero and is sequential. Since you can make assignments to and unset non-contiguous indices ${#array[@]}
is not always the next item at the end of the array.
$ array=(a b c d e f g h)
$ array[42]="i"
$ unset array[2]
$ unset array[3]
$ declare -p array # dump the array so we can see what it contains
declare -a array='([0]="a" [1]="b" [4]="e" [5]="f" [6]="g" [7]="h" [42]="i")'
$ echo ${#array[@]}
7
$ echo ${array[${#array[@]}]}
h
Here's how to get the last index:
$ end=(${!array[@]}) # put all the indices in an array
$ end=${end[@]: -1} # get the last one
$ echo $end
42
That illustrates how to get the last element of an array. You'll often see this:
$ echo ${array[${#array[@]} - 1]}
g
As you can see, because we're dealing with a sparse array, this isn't the last element. This works on both sparse and contiguous arrays, though:
$ echo ${array[@]: -1}
i
${array[@]: start[:count]}
Returns count elems. or, if not specified, all remaining elems. starting at the following elem.: - If start >= 0: from the elem. whose index is >= start. - If start < 0: from the elem. whose index is (last array index + 1) - abs(start); CAVEAT: if abs(start) > (last array index + 1), a null string is returned. If count is specified, as many elements are returned, even if their indices are not contiguous from start.
${array[-1]}
$ declare -a arr
$ arr=("a")
$ arr=("${arr[@]}" "new")
$ echo ${arr[@]}
a new
$ arr=("${arr[@]}" "newest")
$ echo ${arr[@]}
a new newest
arr=("${arr[@]}" "new")
if you have elements with spaces in them
+=
variant is probably much more efficient.
If your array is always sequential and starts at 0, then you can do this:
array[${#array[@]}]='foo'
# gets the length of the array
${#array_name[@]}
If you inadvertently use spaces between the equal sign:
array[${#array[@]}] = 'foo'
Then you will receive an error similar to:
array_name[3]: command not found
+=
syntax (see @e-t172's answer) is (a) simpler, and (b) also works with arrays that are non-contiguous and/or do not start with 0.
+=
was added, eg version 2
$arr += ($el)
seemed to split the string by space and add each of the elements.
With an indexed array, you can to something like this:
declare -a a=()
a+=('foo' 'bar')
Success story sharing
ARRAY
is just a placeholder for an actual variable name. Even if your array indices are not sequential, appending with+=
will simply assign to the highest index + 1.${myarray[@]}
- referencing an array variable as if it were a scalar is the same as accessing its element 0; in other words:$myarray
is the same as${myarray[0]}
.