从数组中删除最后一个元素

k-m*_*man 38 arrays bash

我想删除我的数组中的最后一个条目,我希望数组向我显示它在使用时减少了1个条目${#array[@]}.这是我正在使用的当前行:

unset GreppedURLs[${#GreppedURLs[@]} -1]
Run Code Online (Sandbox Code Playgroud)

请纠正我并告诉我正确的方法.

seh*_*ehe 50

你得到的答案(几乎)对非稀疏索引数组 ¹ 是正确:

unset 'arr[${#arr[@]}-1]'
Run Code Online (Sandbox Code Playgroud)

(注意单引号:它们阻止路径名扩展).

演示:

arr=( a b c )
echo ${#arr[@]}
Run Code Online (Sandbox Code Playgroud)

3

for a in "${arr[@]}"; do echo "$a"; done
Run Code Online (Sandbox Code Playgroud)
a
b
c
Run Code Online (Sandbox Code Playgroud)
unset 'arr[${#arr[@]}-1]'
for a in "${arr[@]}"; do echo "$a"; done
Run Code Online (Sandbox Code Playgroud)
a
b
Run Code Online (Sandbox Code Playgroud)

妙处

echo ${#arr[@]}
Run Code Online (Sandbox Code Playgroud)
2
Run Code Online (Sandbox Code Playgroud)

(GNU bash,版本4.2.8(1)-release(x86_64-pc-linux-gnu))


¹@ Wil提供了一个适用于各种阵列的出色答案


Cit*_*ito 16

您必须先删除空白-1.


Wil*_*Wil 10

如果您想要一个不会吃掉小猫的答案,试试这个:

array=([1]=1 {2..5} [10]=6);
# declare -a array='([1]="1" [2]="2" [3]="3" [4]="4" [5]="5" [10]="6}")'
index=("${!array[@]}");
# declare -a index='([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="10")'
unset 'array[${index[@]: -1}]';
# declare -a array='([1]="1" [2]="2" [3]="3" [4]="4" [5]="5")'
Run Code Online (Sandbox Code Playgroud)

你有它 - 删除最后一个元素.现在,我将提供一个更容易回答,可能满足您的需求,但有一个警告:

array=([1]=1 {2..5} [10]=6);
# declare -a array='([1]="1" [2]="2" [3]="3" [4]="4" [5]="5" [10]="6}")'
array=("${array[@]::${#array[@]}-1}");
# declare -a array='([0]="1" [1]="2" [2]="3" [3]="4" [4]="5")'
Run Code Online (Sandbox Code Playgroud)

这个版本需要一个捷径.它重新索引数组并删除最后一个元素.不幸的是,您还可以看到索引尚未维护.价值观及其顺序一直如此.如果您不关心索引,那么这可能就是您想要的答案.

上述两个答案也适用于bash 4 Associative Arrays.

-

选择的答案并不安全.这是一个例子:

array=([1]=1 {2..5} [10]=6);
# declare -a array='([1]="1" [2]="2" [3]="3" [4]="4" [5]="5" [10]="6")'
unset 'arr[${#arr[@]}-1]';
# declare -a array='([1]="1" [2]="2" [3]="3" [4]="4" [10]="6")'
Run Code Online (Sandbox Code Playgroud)

好的,因为你可以看到它取消了索引为5的元素,因为它错误地计算了数组最后一个元素的索引.它失败了,因为它假设所有数组都是从零开始的,而不是稀疏的.这个答案将在数组开始时失败,除了零之外的任何数组,稀疏的数组,并且对于最后一个元素的'fubar'的关联数组显然必须失败.

  • Bash≥4 中的标准方法是使用 `unset 'arr[-1]'`。顺便说一句,您的回答也是错误的:您的 `unset` 语句中缺少引号,因此您的命令会受到路径名扩展的影响。 (2认同)
  • @sehe:当然它对关联数组不起作用(它将使用键"-1"取消设置字段).但这并不是一个真正的问题:删除关联数组的"last"元素并不是真的有意义(读:它没用).在关联数组的情况下,"last"元素是什么? (2认同)

ImH*_*ere 7

对于任何索引数组(稀疏或非稀疏),因为bash 4.3+(和ksh93 +),这是最简单的解决方案:

unset 'array[-1]'
Run Code Online (Sandbox Code Playgroud)

如果-1是算术表达式或变量,则需要引号来避免bash中的shell扩展.这也正常工作:

a=3; unset 'arr[ a - 4 * 1 ]'
Run Code Online (Sandbox Code Playgroud)

但是如果''将*取消引用(*)将扩展到当前工作目录($pwd)中的文件列表,则无效.

对于较旧的bash版本:从非bash 3.0开始,对于非稀疏数组:

unset 'arr[ ${#arr[@]}-1 ]'
Run Code Online (Sandbox Code Playgroud)

例:

$ arr=( {a..i} ); declare -p arr  
declare -a arr=([0]="a" [1]="b" [2]="c" [3]="d" [4]="e" [5]="f" [6]="g" [7]="h")
$ unset 'arr[ ${#arr[@]}-1 ]'; declare -p arr
declare -a arr=([0]="a" [1]="b" [2]="c" [3]="d" [4]="e" [5]="f" [6]="g")
Run Code Online (Sandbox Code Playgroud)

这会不会对稀疏数组(有一些洞)工作:

$ arr=( {a..g} [9]=i ); declare -p arr
declare -a arr=([0]="a" [1]="b" [2]="c" [3]="d" [4]="e" [5]="f" [6]="g" [9]="i")
$ unset 'arr[ ${#arr[@]}-1 ]'; declare -p arr
declare -a arr=([0]="a" [1]="b" [2]="c" [3]="d" [4]="e" [5]="f" [6]="g" [9]="i")
Run Code Online (Sandbox Code Playgroud)

这是因为元素(计数${#arr[@]})是88-17.
因此,该命令将取消设置arr[7],这不存在.什么都没做.

一个解决方案,也适用于关联数组(无论它可能意味着"未排序列表中的最后一个元素")是生成一个新的索引数组.
然后使用最后一个索引取消设置该元素.

假设arr已经定义(对于bash 3.0+):

$ index=( "${!arr[@]}" )          # makes index non-sparse.
$ unset 'arr[${index[@]}-1]'      # unset the last index.
$ declare -p arr
declare -a arr=([0]="a" [1]="b" [2]="c" [3]="d" [4]="e" [5]="f" [6]="g")
Run Code Online (Sandbox Code Playgroud)

一个稍微更便携(在ksh93中工作),看起来很难看,解决方案是:

$ arr=( {a..e} [9]=i )
$ index=( "${!arr[@]}" )
$ unset "arr[  ${index[${#index[@]}-1]}  ]"   # Yes, double quotes.
$ declare -p arr
declare -a arr=([0]="a" [1]="b" [2]="c" [3]="d" [4]="e")   
Run Code Online (Sandbox Code Playgroud)

或者(同样,ksh的双引号):

$ unset "arr[${index[@]: -1}]"
Run Code Online (Sandbox Code Playgroud)

如果要避免空格和负数,请将其设为变量:

$ a="-1"; unset "arr[${index[@]:a}]"
Run Code Online (Sandbox Code Playgroud)