ChatGPT解决这个技术问题 Extra ChatGPT

在 Bash 中不指定索引的情况下向数组添加新元素

有没有办法在 bash 中做类似 PHPs $array[] = 'foo'; 的事情:

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

U
U. Windl

就在这里:

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

Bash Reference Manual

在赋值语句为 shell 变量或数组索引(请参阅数组)赋值的上下文中,'+=' 运算符可用于附加或添加到变量的先前值。

还:

当使用复合赋值将 += 应用于数组变量时(请参阅下面的数组),变量的值不会取消设置(就像使用 = 时一样),并且新值将从数组的最大索引大 1 开始附加到数组(对于索引数组)


这适用于 bash 3.2.48 (OS X 10.8.2)。请注意,ARRAY 只是实际变量名称的占位符。即使您的数组索引是连续的,附加 += 只会分配给最高索引 + 1。
bash 版本 4.2.24(1) 中有类似的东西吗?
需要注意的是,ARRAY+=('foo') 与 ARRAY+='foo' 不同,后者将字符串 'foo' 附加到具有最低 (?) 键的条目中。
根据 wiki.bash-hackers.org/scripting/bashchanges,这种语法最早出现在 3.1-alpha1 版本中。
@Jas:要访问 整个 数组,您必须使用 ${myarray[@]} - 将数组变量作为标量引用与访问其元素 0 相同;换句话说:$myarray${myarray[0]} 相同。
D
Dennis Williamson

正如 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

好东西;从来不知道子字符串提取语法也可以应用于数组;通过反复试验确定的规则是(bash 3.2.48): ${array[@]: start[:count]} 返回计数元素。或者,如果未指定,则为所有 remaining 元素。从以下元素开始: - 如果 start >= 0:从元素开始。其索引是>= start。 - 如果开始 < 0:来自元素。其索引为 (last array index + 1) - abs(start);注意:如果 abs(start) > (最后一个数组索引 + 1),返回一个空字符串。如果指定了 count ,则返回尽可能多的元素,即使它们的索引从一开始就不连续。
@mklement:在 Bash 4.2 中,您可以使用负数组下标来访问从数组末尾开始计数的元素。 ${array[-1]}
很高兴知道,谢谢。 OS X(截至 10.8.2)仍然使用 3.2.48,stackoverflow.com/questions/10418616/… 告诉我,不幸的是,“Apple 使用的是相当旧的 Bash 版本,因为他们不发布根据 GPL3 许可的代码。”
Z
Zenexer
$ declare -a arr
$ arr=("a")
$ arr=("${arr[@]}" "new")
$ echo ${arr[@]}
a new
$ arr=("${arr[@]}" "newest")
$ echo ${arr[@]}
a new newest

非常适合不支持由 e-t172 解释的 += 运算符语义的 bash 版本
一个很好的向后兼容解决方案,但请注意,如果任何现有元素中有空格,它们将被拆分为多个元素;如果您的元素中有空格,请使用 arr=("${arr[@]}" "new")
这也可以用来推到阵前,正是我所需要的。
如果您的数组有数百个长字符串,那么 += 变体可能更有效。
j
jww

如果您的数组始终是连续的并且从 0 开始,那么您可以这样做:

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

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

如果您无意中在等号之间使用了空格:

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

然后您将收到类似于以下内容的错误:

array_name[3]: command not found

是的,您可以,但是 += 语法(请参阅@e-t172 的答案)(a)更简单,并且(b)也适用于不连续和/或不以 0 开头的数组。
老实说,这个解决方案(对我来说)比“+=”效果更好,因为后者的长度有时是错误的(添加一个元素时增加两个)......所以我更喜欢这个回复! :)
这也适用于早期版本的 bash,在添加 += 之前,例如版本 2
当您的元素中有空格时,这也有效 - $arr += ($el) 似乎将字符串按空格拆分并添加每个元素。
c
codeforester

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

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