When using bash arrays, you can remove an element in the following manner:
unset array[i] # where i is the array index
The problem with this is after the unset ${array[@]] is not truly valid. Yes it does give you the number of active array elements, but not the actual array depth. The index of the removed index in the array still exists. It simply has been set inactive/null. For example:
declare -a array=( a b c d e )
unset array[2]
for ((i=0; i < ${#array[@]}; i++)) ; do
echo "$i: ${array[$i]}"
done
outputs the following:
0: a
1: b
2:
3: d
array[2] is still there but set to null or inactive
array[4] (e) does not show because ${#array[@]} is the number of active array elements and not the true array element depth. This gets very messy very quickly each time an element is unset
As an example consider the following code:
# array contains 0 or more strings # remove looks for and removes a given string
remove () {
local str=$1
for (( i = 0 ; i < ${#array[@]}; i++ )) ; do
if [[ "${array[$i]}" == "$str" ]] ; then
unset array[$i]
return 0
fi
done
echo "$str: not registered"
return 0
}
This is only valid the first time remove is called. After that, valid elements may be missed.
One fix for this is to added the following line after the unset:
unset array[$i]
+ array=( "${array[@]}" )
This re-initializes array with the element completely removed.
The problem, this feels kludgy.
So my questions are this:
1) is there a way of getting the true array element depth?
2) is there a way of detecting the end of an array when iterating through it?
3) is there another cleaner solution?