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

Arrays 从数组中删除最后一个元素,arrays,bash,Arrays,Bash,我想删除数组中的最后一个条目,我想让数组显示,当我使用${#array[@]}时,它少了一个条目。这是我正在使用的当前行: unset GreppedURLs[${#GreppedURLs[@]} -1] 请纠正我并告诉我正确的方法。你的答案(几乎)是正确的 Bash 4.3或更高版本添加了此新语法以执行相同的操作: unset arr[-1] (注意单引号:它们阻止路径名扩展) 演示: arr=(a b c) 回声${#arr[@]} 三, 笑点 echo ${#arr[@]} (G

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

unset GreppedURLs[${#GreppedURLs[@]} -1]
请纠正我并告诉我正确的方法。

你的答案(几乎)是正确的

Bash 4.3或更高版本添加了此新语法以执行相同的操作:

 unset arr[-1]
(注意单引号:它们阻止路径名扩展)

演示:

arr=(a b c)
回声${#arr[@]}
三,

笑点

echo ${#arr[@]}
(GNUBash,版本4.2.8(1)-发行版(x86_64-pc-linux-GNU))



< P>>@ WIL提供了一种适用于各种数组

的方法,必须在代码> > 1</代码>之前删除空白。

< p>如果你想要一个不会吃小猫的答案,试试这个:

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")'
这就是它——删除最后一个元素。现在,我将给出一个更简单的答案,它可能满足您的需求,但有一个警告:

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")'
这个版本有一个快捷方式。它重新索引数组并删除最后一个元素。不幸的是,您还可以看到索引没有得到维护。这些值及其顺序已被修改。如果你不关心索引,那么这可能就是你想要的答案

以上两个答案同样适用于

--

选择的答案并不安全。下面是一个例子:

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")'
好的,正如您所看到的,它正在取消索引为5的元素的设置,因为它错误地计算了数组最后一个元素的索引。它失败了,因为它假设所有数组都是零基的,而不是稀疏的。这个答案在以零以外的任何数组开始的数组(稀疏数组)上都会失败,对于最后一个元素为“fubar”的关联数组,显然必须失败。

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

unset 'array[-1]'
如果-1是算术表达式或变量,则需要引号来避免bash中的shell扩展。这也可以正常工作:

a=3; unset 'arr[ a - 4 * 1 ]'
但如果不加引号(
'
),则不起作用,因为*将扩展到当前工作目录中的文件列表(
$pwd

对于较旧的bash版本:这在bash 3.0之后适用于非稀疏阵列:

unset 'arr[ ${#arr[@]}-1 ]'
例如:

$ 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")
这将适用于稀疏阵列(带有一些孔):

这是因为元素的计数(
${arr[@]}
)是
8
8-1
7

因此,该命令将取消设置不存在的
arr[7]
。什么也没做

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

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

一种更便携(适用于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")   
或者(同样,ksh的双引号):

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

$ a="-1"; unset "arr[${index[@]:a}]"

下面的代码对Mac很有用/bash@3.x和Linux(ubuntu/bash@4.x)

详情如下:

len=${#arr[@]}
idx=$[$len-1]    # <=> $(($len-1))
unset arr[$idx]
len=${#arr[@]}
idx=$[$len-1]#$($len-1))
未设置arr[$idx]

在函数中,可以添加以下内容:

target="${@:$(($#)):1}"
set -- "${@:1:$(($#-1))}"

适用于GNU bash版本3.1.0(3)-发行版(sparc-sun-solaris2.9)@Wil我不同意重复的“错误”和“根本错误”等。您的答案是可靠的,并且您得到了+1。这个答案不是“错”,而是不太一般。在最初的问题中,我什么也不说。更不用说,当这个问题被提出时,Bash4是非常罕见的。如果可以的话,我很乐意把你的答案交给你,因为你的答案是最新的。如果您重新考虑所有不必要的竞争修辞,我将不胜感激。@sehe原始问题的数据集没有提供,这就是为什么我说您的答案是错误的-因为它对数据集做出了盲目的假设。。。如果你想称我的评论为“竞争修辞”,那么,哈哈。。。你有权看起来像那样说话。在这里使用双引号是否等效?@GézaTörök“当然”该功能是从zsh复制的。这很好,但要知道它是在Bash4.3中添加的(在这个答案编写好几年之后)。并非每个系统都有最近的bash。例如,Ubuntu LTS几乎没有它(4.4)。用Bash中的标准方式更新了答案文本≥4是只使用
unset'arr[-1]'
。顺便说一句,您的答案也是错误的:
unset
语句中缺少引号,因此您的命令需要进行路径名扩展。@gniourf\u gniourf这对关联数组有好处吗?那将是大满贯answer@sehe:当然,对于关联数组,它不能按预期工作(它将用键
-1
取消设置字段)。但这并不是一个真正的问题:删除关联数组的“最后一个”元素实际上没有意义(请阅读:它没有用处);关联数组中的“最后”元素是什么?@gniourf_gniourf这是一个很好的点;的确当然,未指定的顺序是确定的-因此您/可以/向用户显示列表,并声称让用户“删除显示的最后一个条目”是有用的。但这是相当做作的。谢谢你让我仔细考虑。@gniourf\gniourf TY为指针重新引用未设置的参数。要回答您关于删除assoc数组的最后一个元素是否有用的问题,如果要从列表中弹出键/值对,该怎么办?你说的顺序没有得到维护是对的,但这并不妨碍它发挥作用。我喜欢
unset'array[-1]'
的简洁性,但遗憾的是,它在bash v4中不是有效的命令,bash v4是我的操作系统可用的最新版本。不过,我以后会记住它。@CameronHudson然后从bash3开始使用
unset'数组[${index[@]}-1]
unset 'arr[ ${#arr[@]}-1 ]'
$ 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")
$ 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")
$ 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")
$ 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")   
$ unset "arr[${index[@]: -1}]"
$ a="-1"; unset "arr[${index[@]:a}]"
unset arr[$[${#arr[@]}-1]] # non-sparse array only
len=${#arr[@]}
idx=$[$len-1]    # <=> $(($len-1))
unset arr[$idx]
target="${@:$(($#)):1}"
set -- "${@:1:$(($#-1))}"