One thing to bear in mind is that bash
implemented arrays like ksh
, that is as associative arrays where keys are limited to positive integers (contrary to other languages like perl
or zsh
for instance).
In:
a[123]=foo a[456]=bar a[789]=baz
In bash, you've got an associative array with 3 elements, while in perl
, you'd have an array with 790 elements (789 with zsh).
In ksh
or bash
, ${a[@]:0}
returns the first element of the array in the list of elements sorted by indices. So in that case, it returns ${a[123]}
, not ${a[0]}
.
unset 'a[123]'
(remember to quote it, otherwise it would fail if there was a file called a1 or a2 or a3 in the current directory) makes sense, as it removes a particular key in the array.
unset 'a[@]::2'
makes less sense though. bash
only understands unset a
, unset 'a[123]'
or unset 'a[*/@]'
, anything after is ignored, so unset 'a[@]::2'
and unset 'a[@]please'
do the same: unset the whole array.
If you want to unset a range of keys, you'd need to loop through the keys:
To get the list of keys of the array, the syntax is "${!a[@]}"
. Unfortunately, applying a range to that doesn't work with bash
nor ksh
, so you'd need a temporary array:
keys=("${!a[@]}")
for i in "${keys[@]::2}"; do unset "a[$i]"; done
Now if you want to consider those arrays like in other languages, you don't want to use unset
. Like, if the array is not sparse in the first place and you want to keep it so (that is shift all the elements by 2 instead of unsetting the first two), you can do things like:
a=("${a[@]:2}")
That is reassign the array with the list of elements you want to keep.
For comparison, with zsh
.
a=({1..20})
unset 'a[12,16]'
would set an empty value to elements 12 to 16. while unset 'a[16,20]'
would shrink the array to 15 elements.
a=({1..20})
a[12,16]=()
(still with zsh
) would shift elements 17 to 20 by 5 positions so a[12]
would contain 17
.