在Bash中向数组添加新元素时不指定索引

972

在Bash中是否有像PHP的$array[] = 'foo';这样的方式,而不是使用:

array[0]='foo'
array[1]='bar'

如何在Bash中向数组添加/删除元素?(https://unix.stackexchange.com/q/328882/72456) - αғsнιη
7个回答

1878

是的,有这个功能:

ARRAY=()
ARRAY+=('foo')
ARRAY+=('bar')

Bash参考手册

在赋值操作符将一个值分配给shell变量或数组索引(请参见数组)的情况下,可以使用“+=”运算符来附加或添加到变量的先前值。

此外:

当使用复合赋值(请参见下面的数组)向数组变量应用+=时,变量的值不会被取消设置(如使用=时),并且新值将追加到数组的末尾,开始位置为索引的最大值加1(对于索引数组)。


29
这在bash 3.2.48 (OS X 10.8.2)上完全正常运行。请注意,“ARRAY”只是实际变量名称的占位符。即使数组索引不是连续的,使用“+=”添加元素也会将其分配给最高索引+1。 - mklement0
6
在Bash版本4.2.24(1)中有类似的东西吗? - Ali Ismayilov
233
需要注意的是,ARRAY+=('foo') 与 ARRAY+='foo' 是完全不同的操作。前者将字符串 'foo' 作为一个新元素添加到数组中,而后者则将字符串 'foo' 添加到键值最低的元素中。 - TheConstructor
9
根据 http://wiki.bash-hackers.org/scripting/bashchanges,这种语法首次出现在 3.1-alpha1 版本中。 - David Yaw
53
要访问整个数组,您必须使用${myarray[@]}。将数组变量像标量一样引用是访问其第0个元素的同义词;换句话说:$myarray${myarray[0]}是相同的。 - mklement0
显示剩余12条评论

93

正如Dumb Guy所指出的,重要的是要注意数组是否从零开始且连续。由于可以对非连续索引进行赋值和取消设置,因此${#array[@]}并不总是在数组末尾的下一个项目。

$ array=(a b c d e f g h)
$ array[42]="i"
$ unset array[2]
$ unset array[3]
$ declare -p array     # dump the array so we can see what it contains
declare -a array='([0]="a" [1]="b" [4]="e" [5]="f" [6]="g" [7]="h" [42]="i")'
$ echo ${#array[@]}
7
$ echo ${array[${#array[@]}]}
h

以下是获取最后一个索引的方法:

$ end=(${!array[@]})   # put all the indices in an array
$ end=${end[@]: -1}    # get the last one
$ echo $end
42

这说明了如何获取数组的最后一个元素。通常会看到以下代码:

$ echo ${array[${#array[@]} - 1]}
g

正如您所看到的,由于我们正在处理稀疏数组,因此这不是最后一个元素。尽管如此,该方法对稀疏数组和连续数组都适用:

$ echo ${array[@]: -1}
i

5
很棒的东西;我从未想到子字符串提取语法也可以应用于数组;根据试错确定的规则(bash 3.2.48)如下: ${array[@]: start[:count]} 返回 count 个元素,如果未指定,则返回以下元素中的所有“剩余”元素:
  • 如果 start >= 0:从索引大于等于 start 的元素开始。
  • 如果 start < 0:从索引为 (last array index + 1) - abs(start) 的元素开始; 注意:如果 abs(start) > (last array index + 1),则返回空字符串。 如果指定了 count,将返回同样数量的元素,即使它们的索引从 start 开始不具有连续性。
- mklement0
6
在Bash 4.2中,您可以使用负数数组下标来访问从数组结尾计数的元素。${array[-1]} - Dennis Williamson
1
知道这点很好,谢谢。截至OS X 10.8.2,仍在使用3.2.48版本,并且https://dev59.com/vmPVa4cB1Zd3GeqP5GF6告诉我,不幸的是,“苹果使用相当旧的Bash版本,因为他们不提供根据GPL3许可的代码。” - mklement0

67
$ declare -a arr
$ arr=("a")
$ arr=("${arr[@]}" "new")
$ echo ${arr[@]}
a new
$ arr=("${arr[@]}" "newest")
$ echo ${arr[@]}
a new newest

13
适用于不支持 e-t172 解释的 += 运算符语义的 Bash 版本。 - akostadinov
17
一个很好的向后兼容的解决方案,但要注意,如果任何现有元素中有空格,它们将被分成多个元素; 如果您的元素中包含空格,请使用arr=("${arr[@]}" "new") - kbolino
2
这也可以用于将元素推到数组前面,这正是我所需要的。 - Tomáš Zato
如果您的数组有数百个长字符串,则“+=”变量可能更有效。 - U. Windl

36
如果你的数组始终是连续的,从0开始,那么你可以这样做:
array[${#array[@]}]='foo'

# gets the length of the array
${#array_name[@]}

如果你不小心在等号之间使用了空格:

array[${#array[@]}] = 'foo'

然后你会收到类似的错误信息:

array_name[3]: command not found

7
可以的,但是 += 语法(见 @e-t172 的回答)更加简单,并且也适用于非连续和/或不以0开始的数组。 - mklement0
说实话,对我来说,这个解决方案比“+=”更好,因为后者长度有时会出错(添加一个元素时增加两个)...所以我更喜欢这个答复! :) - Pierpaolo Cira
这在早期版本的bash中也适用,例如2.x版本,此时还未添加+= - Zoey Hewll
1
当您的元素中包含空格时,这也适用 - $arr += ($el) 似乎会将字符串按空格分割并添加每个元素。 - Max

10

使用索引数组,您可以像这样操作:

declare -a a=()
a+=('foo' 'bar')

1

添加 元素

array+=("${element}")

追加另一个数组

array+=("${array[@]}")

追加命令输出

readarray -t output < <(command)
array+=("${output[@]}")

0
也请看一下这个:
test_array=(1 2 3 4)
test_array+=(5)
echo "${test_array[@]}"

结果: 1 2 3 4 5 < p > 使用+=运算符可以将单个元素或多个元素附加到数组中,例如,您可以像这样向数组附加更多元素:

test_array+=(6 7 8 9)
echo "${test_array[@]}"

结果:1 2 3 4 5 6 7 8 9
我想提一下,在Bash中,你也可以通过不指定索引来从数组中删除元素,你可以使用unset命令和元素的值。
test_array=(1 2 3 4 5)
unset test_array[2]
echo "${test_array[@]}" 

结果:1 2 4 5
注意,当你从数组中移除一个元素时,剩余元素的索引会相应地调整。在上面的例子中,当我移除值为3的第三个元素时,第四个和第五个元素分别成为新的第三个和第四个元素。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接