使用bash数组时,可以通过以下方式移除元素:
unset array[i] # where i is the array index
问题出在未设置的${array@]不是真正有效之后。是的,它确实给出了活动数组元素的数量,但不是实际的数组深度。数组中删除的索引的索引仍然存在。它只是被设置为无效/空。例如:
declare -a array=( a b c d e )
unset array[2]
for ((i=0; i < ${#array[@]}; i++)) ; do
echo "$i: ${array[$i]}"
done
输出以下内容:
0: a
1: b
2:
3: d
array2仍然存在,但设置为null或inactive
数组数组不显示,因为${#4@}是活动数组元素的数量,而不是真正的数组元素深度。每次取消设置一个元素时,这很快就会变得非常混乱
作为示例,请考虑以下代码:
array包含0个或多个字符串# remove查找并删除给定的字符串
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
}
这只在第一次调用remove时有效。在此之后,可能会丢失有效的元素。
解决此问题的一种方法是在unset之后添加以下行:
unset array[$i]
+ array=( "${array[@]}" )
这将在完全删除元素的情况下重新初始化数组。
问题是,这让人感觉很笨拙。
所以我的问题是:
1)有没有办法得到真正的数组元素深度?
2)当迭代数组时,有没有办法检测数组的结尾?
3)有没有其他更干净的解决方案?
发布于 2018-09-17 00:36:11
了解for ((i=0; i<${#array[@]}; i++))
崩溃的原因
这里没有你所要求的“真正的数组元素深度”这样的东西。Bash数组并不是真正的数组--它们是散列映射(常规数组按数字索引,bash 4.0的新“关联数组”按字符串索引)。因此,键完全没有理由从0开始--您可以有一个如下所示的数组:declare -a array=( [1000]="one thousand" [2000]="two thousand" [3000]="three thousand" )
,它的长度正好是3;在这些项之间没有一堆NUL/空元素(分别用键1000
、2000
和3000
查找)。
从稀疏数组中安全地删除元素
如果要按索引删除,则遍历索引。"${array[@]}"
遍历数组中的项,而"${!array[@]}"
(请注意!
)遍历可以查找这些项的索引。
正如您已经观察到的,假设索引的范围从0到数组中的总项数是不安全的,因为bash数组是允许稀疏的--但是没有理由在一开始就编写代码来做这样的假设。
for array_idx in "${!array[@]}"; do
unset "array[$array_idx]"
done
https://stackoverflow.com/questions/52355927
复制相似问题