首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >从Bash数组中删除元素时出现不一致

从Bash数组中删除元素时出现不一致
EN

Stack Overflow用户
提问于 2018-09-17 00:03:17
回答 1查看 84关注 0票数 4

使用bash数组时,可以通过以下方式移除元素:

代码语言:javascript
复制
unset array[i]   # where i is the array index

问题出在未设置的${array@]不是真正有效之后。是的,它确实给出了活动数组元素的数量,但不是实际的数组深度。数组中删除的索引的索引仍然存在。它只是被设置为无效/空。例如:

代码语言:javascript
复制
declare -a array=( a b c d e )
unset array[2]

for ((i=0; i < ${#array[@]}; i++)) ; do
    echo "$i: ${array[$i]}"
done

输出以下内容:

代码语言:javascript
复制
0: a
1: b
2:
3: d

array2仍然存在,但设置为null或inactive

数组数组不显示,因为${#4@}是活动数组元素的数量,而不是真正的数组元素深度。每次取消设置一个元素时,这很快就会变得非常混乱

作为示例,请考虑以下代码:

array包含0个或多个字符串# remove查找并删除给定的字符串

代码语言:javascript
复制
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之后添加以下行:

代码语言:javascript
复制
     unset array[$i]
  +  array=( "${array[@]}" )

这将在完全删除元素的情况下重新初始化数组。

问题是,这让人感觉很笨拙。

所以我的问题是:

1)有没有办法得到真正的数组元素深度?

2)当迭代数组时,有没有办法检测数组的结尾?

3)有没有其他更干净的解决方案?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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/空元素(分别用键100020003000查找)。

从稀疏数组中安全地删除元素

如果要按索引删除,则遍历索引。"${array[@]}"遍历数组中的项,而"${!array[@]}" (请注意!)遍历可以查找这些项的索引。

正如您已经观察到的,假设索引的范围从0到数组中的总项数是不安全的,因为bash数组是允许稀疏的--但是没有理由在一开始就编写代码来做这样的假设。

代码语言:javascript
复制
for array_idx in "${!array[@]}"; do
  unset "array[$array_idx]"
done
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52355927

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档