bash 从数组中删除最后一个元素
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8247433/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Remove the last element from an array
提问by k-man
I want to remove the last entry in my array, and I want the array to show me that it has 1 less entry when I am using the ${#array[@]}
. This is the current line I am using:
我想删除数组中的最后一个条目,并且我希望数组在我使用${#array[@]}
. 这是我正在使用的当前行:
unset GreppedURLs[${#GreppedURLs[@]} -1]
Please correct me and show me the right way.
请纠正我并告诉我正确的方法。
回答by sehe
The answer you have is (nearly) correct for non-sparse indexed arrays1:
unset 'arr[${#arr[@]}-1]'
Bash 4.3 or higher added this new syntax to do the same:
unset arr[-1]
Bash 4.3 或更高版本添加了这个新语法来做同样的事情:
unset arr[-1]
(Note the single quotes: they prevent pathname expansion).
(注意单引号:它们防止路径名扩展)。
Demo:
演示:
arr=( a b c )
echo ${#arr[@]}
3
3
for a in "${arr[@]}"; do echo "$a"; done
a b c
a b c
unset 'arr[${#arr[@]}-1]'
for a in "${arr[@]}"; do echo "$a"; done
a b
a b
Punchline
妙处
echo ${#arr[@]}
2
2
(GNU bash, version 4.2.8(1)-release (x86_64-pc-linux-gnu))
(GNU bash,版本 4.2.8(1)-release (x86_64-pc-linux-gnu))
1 @Wil provided an excellent answerthat works for all kinds of arrays
1 @Wil 提供了一个适用于各种数组的优秀答案
回答by Cito
You must remove the blank before -1
.
您必须删除之前的空白-1
。
回答by Wil
If you'd like an answer which won't eat your kittens, try this:
如果你想要一个不会吃掉你的小猫的答案,试试这个:
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")'
And there you have it - removing the last element. Now I'll present a much easier answer which probably meets your needs but has a caveat:
你有它 - 删除最后一个元素。现在我将提出一个更简单的答案,它可能满足您的需求,但有一个警告:
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")'
This version takes a shortcut. It re-indexes the array and drops the last element. Unfortunately you can also see that the index has not been maintained. The values and their order has been. If you don't care about the index then this is probably the answer you wanted.
这个版本走捷径。它重新索引数组并删除最后一个元素。不幸的是,您还可以看到索引尚未维护。值和它们的顺序是。如果您不关心索引,那么这可能就是您想要的答案。
Both of the above answers will also work on bash 4 Associative Arrays.
以上两个答案也适用于bash 4 Associative Arrays。
--
——
The chosen answer is not safe. Here's an example:
选择的答案不安全。下面是一个例子:
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")'
Okay so as you can see it is unsetting the element with index 5 because it incorrectly calculated the index of the last element of the array. It failed because it operated on an assumption that all arrays are zero-based, and not sparse. This answer will fail on arrays starting with anything other than zero, arrays which are sparse, and obviously must fail for an associative array with 'fubar' for the last element.
好的,如您所见,它正在取消设置索引为 5 的元素,因为它错误地计算了数组最后一个元素的索引。它失败了,因为它假设所有数组都是从零开始的,而不是稀疏的。这个答案将在以零以外的任何数组开头的数组上失败,数组是稀疏的,并且显然对于最后一个元素带有 'fubar' 的关联数组必须失败。
回答by Isaac
For any indexed array (sparse or not), since bash 4.3+ (and ksh93+), this is the simplest of solutions:
对于任何索引数组(稀疏与否),自 bash 4.3+(和 ksh93+)以来,这是最简单的解决方案:
unset 'array[-1]'
The quotes are needed to avoid shell expansion in bash if the -1 is an arithmetic expression or a variable. This also works correctly:
如果 -1 是算术表达式或变量,则需要使用引号来避免 bash 中的 shell 扩展。这也可以正常工作:
a=3; unset 'arr[ a - 4 * 1 ]'
But will not work if unquoted (''
) as the * will be expanded to the list of files in the present working directory ($pwd
).
但如果不加引号 ( ''
)将不起作用,因为 * 将扩展到当前工作目录 ( $pwd
)中的文件列表。
For older bash versions: this works since bash 3.0 for non-sparse arrays:
对于较旧的 bash 版本:这适用于非稀疏数组的 bash 3.0:
unset 'arr[ ${#arr[@]}-1 ]'
Example:
例子:
$ 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")
This will notwork for sparse arrays (with some holes):
这不适用于稀疏数组(有一些漏洞):
$ 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")
This happens because the count of elements (${#arr[@]}
) is 8
and 8-1
is 7
.
So, the command will unset arr[7]
, which doesn't exist. Nothing is done.
发生这种情况是因为元素 ( ${#arr[@]}
)的计数是8
并且8-1
是7
。
因此,该命令将 unset arr[7]
,它不存在。什么都没做。
A solution, that also work for Associative arrays (in whatever it could mean "the last element" in an unsorted list) is to generate a new array of indexes.
Then use the last index to unset that element.
一个也适用于关联数组的解决方案(无论它可能意味着未排序列表中的“最后一个元素”)是生成一个新的索引数组。
然后使用最后一个索引来取消设置该元素。
Assuming arr
is already defined (for bash 3.0+):
假设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")
A slightly more portable (works in ksh93), that looks ugly, solution is:
稍微更便携(在 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")
Or (again, double quotes for ksh):
或者(再次,ksh 的双引号):
$ unset "arr[${index[@]: -1}]"
If you want to avoid the space and the negative number, make it a variable:
如果要避免空格和负数,请将其设为变量:
$ a="-1"; unset "arr[${index[@]:a}]"
回答by Дмитрий Юдин
The following works fine for Mac/[email protected] and Linux (ubuntu/[email protected])
以下适用于 Mac/[email protected] 和 Linux (ubuntu/[email protected])
unset arr[$[${#arr[@]}-1]] # non-sparse array only
in more details:
更多细节:
len=${#arr[@]}
idx=$[$len-1] # <=> $(($len-1))
unset arr[$idx]