如何从数组中完全删除元素?


48

unset array[0]删除元素,但是如果我仍然echo ${array[0]}得到null值,还有其他方法可以执行此操作,但是如果数组的元素包含如下所示的空格

array[0]='james young'
array[1]='mary'
array[2]='randy orton'

但是这些也做不到

array=${array[@]:1} #removed the 1st element

现在我希望新数组像

array[0]='mary'
array[1]='randy orton'

分配后,空格会引起麻烦,实际数组变得像替换一样。

array=(mary randy orton)

4
不,不是空格引起麻烦,而是缺少报价。
manatwork

Answers:


68

只需在赋值上使用数组语法并引用变量即可:

array=("${array[@]:1}") #removed the 1st element

根据评论中的问题进行编辑。对于$@您可以使用它像这样:

set -- "${@:2}" #removed the 1st parameter

8
请注意,它不会删除第一个元素,而是删除索引0的元素并重新分配索引。如果第一个元素位于indice 12上,它将不会删除任何内容,但将重新分配索引,以使曾经在indice 12上的内容现在位于indice 0上。在OP的情况下这可能不是问题,但应该注意以后的参考。行为与zshksh或bash相反,其数组不是稀疏的,这是不同的。
斯特凡Chazelas

3
嗨@StephaneChazelas “索引”的单数形式是“ 索引 ”。谢谢你的评论!
史蒂文·卢

3
@manatwork-re:您的编辑-为什么不使用shift
don_crissti

1
@don_crissti,很好。我专注于索引差异,不再赘述。还需要记住一些情况,当您需要丢弃可变数量的项目时,例如要精确保留最后3个:array=("${array[@]: -3}")set -- "${@: -3}"。因此陷入困境。
manatwork's

1
shift $[$#-3]最后3个可能更快$@
Tino

0

这让我思考。sed / awk / tail的问题在于它们是逐行的。删除第一行之后,您必须将其他所有行从模式空间写入文件。

  • 您可以使用以下命令在几秒钟内完成所需的操作。
  • 这会将整个文件写入数组。
  • 删除第一行,因为它会将其转储回文件中。

    readarray -t aLargeFile < <(cat largefile)
    echo "${aLargeFile[@]:1}" >largefile

只需将更largefile改为文件名。


为什么不使用它sed -i 1d largefile呢?这甚至适用于大于RAM + swap的文件
Tino

0

要删除特定索引处的元素,我们可以使用unset然后复制到另一个数组。unset在这种情况下,仅不需要。因为unset不删除元素,所以只将空字符串设置为数组中的特定索引。

declare -a arr=('aa' 'bb' 'cc' 'dd' 'ee')
unset 'arr[1]'
declare -a arr2=()
i=0
for element in ${arr[@]}
do
    arr2[$i]=$element
    ((++i))
done
echo ${arr[@]}
echo "1st val is ${arr[1]}, 2nd val is ${arr[2]}"
echo ${arr2[@]}
echo "1st val is ${arr2[1]}, 2nd val is ${arr2[2]}"

输出是

aa cc dd ee
1st val is , 2nd val is cc
aa cc dd ee
1st val is cc, 2nd val is dd

-1
#!/bin/bash

q=( one two three four five )

echo -e "
  (remove) { [:range:] } <- [:list:]
                | [:range:] => return list with range removed range is in the form of [:digit:]-[:digit:]
"

function remove {
  if [[ $1 =~ ([[:digit:]])(-([[:digit:]]))?   ]]; then
    from=${BASH_REMATCH[1]}
    to=${BASH_REMATCH[3]}
  else
    echo bad range
  fi;shift
  array=( ${@} )
  local start=${array[@]::${from}}
  local rest
  [ -n "$to" ] && rest=${array[@]:((${to}+1))}  || rest=${array[@]:((${from}+1))}
  echo ${start[@]} ${rest[@]}
}

q=( `remove 1 ${q[*]}` )
echo ${q[@]}
~                                                                                                                                                              
~                       

4
如果有一些解释它是如何工作的,而不仅仅是一小段代码,那会更好。底部的波浪号是什么?
2013年

3
说真的,你是正确的。看起来确实像是流氓写的,但是谢谢。我真的只能在汉堡包上两天之间偷偷摸摸。
MageProspero

如果q的任何元素中都有空格,则将其分解为多个元素。
威廉·埃弗里特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.