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.
请纠正我,告诉我正确的方法。
4 个解决方案
#1
36
The answer you have is (nearly) correct for non-sparse indexed arrays¹:
答案是(几乎)纠正non-sparse¹索引数组:
unset 'arr[${#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
unset 'arr[${#arr[@]}-1]'
for a in "${arr[@]}"; do echo "$a"; done
a b
Punchline
笑点
echo ${#arr[@]}
2
(GNU bash, version 4.2.8(1)-release (x86_64-pc-linux-gnu))
(GNU bash,版本4.2.8(1)-发布(x86_64-pc-linux-gnu))
¹ @Wil provided an excellent answer that works for all kinds of arrays
¹@Wil提供了一个很好的回答,适用于所有类型的数组
#2
16
You must remove the blank before -1
.
必须在-1之前删除空格。
#3
4
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关联数组。
--
- - -
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取消元素的设置因为它错误地计算了数组最后一个元素的索引。它之所以失败,是因为它假定所有数组都是基于零的,而不是稀疏的。这个答案对于数组来说是失败的,除了0,数组是稀疏的,显然对于最后一个元素的关联数组必须是失败的。
#4
3
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 not work 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。因此,命令将解除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}]"
#1
36
The answer you have is (nearly) correct for non-sparse indexed arrays¹:
答案是(几乎)纠正non-sparse¹索引数组:
unset 'arr[${#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
unset 'arr[${#arr[@]}-1]'
for a in "${arr[@]}"; do echo "$a"; done
a b
Punchline
笑点
echo ${#arr[@]}
2
(GNU bash, version 4.2.8(1)-release (x86_64-pc-linux-gnu))
(GNU bash,版本4.2.8(1)-发布(x86_64-pc-linux-gnu))
¹ @Wil provided an excellent answer that works for all kinds of arrays
¹@Wil提供了一个很好的回答,适用于所有类型的数组
#2
16
You must remove the blank before -1
.
必须在-1之前删除空格。
#3
4
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关联数组。
--
- - -
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取消元素的设置因为它错误地计算了数组最后一个元素的索引。它之所以失败,是因为它假定所有数组都是基于零的,而不是稀疏的。这个答案对于数组来说是失败的,除了0,数组是稀疏的,显然对于最后一个元素的关联数组必须是失败的。
#4
3
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 not work 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。因此,命令将解除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}]"