Fügen Sie einem Array ein neues Element hinzu, ohne den Index in Bash anzugeben

793

Gibt es eine Möglichkeit, so etwas wie PHPs $array[] = 'foo';in Bash oder Doing zu machen:

array[0]='foo'
array[1]='bar'
Darryl Hein
quelle
" Wie füge
ich

Antworten:

1540

Ja da ist:

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

Bash Referenzhandbuch :

In dem Kontext, in dem eine Zuweisungsanweisung einer Shell-Variablen oder einem Array-Index einen Wert zuweist (siehe Arrays), kann der Operator '+ =' verwendet werden, um den vorherigen Wert der Variablen anzuhängen oder zu ergänzen.

Etienne Dechamps
quelle
21
Dies funktioniert gut mit Bash 3.2.48 (OS X 10.8.2). Beachten Sie, dass dies ARRAYnur ein Platzhalter für einen tatsächlichen Variablennamen ist. Selbst wenn Ihre Array-Indizes nicht sequentiell sind, wird das Anhängen mit +=einfach dem höchsten Index + 1
zugewiesen.
3
Gibt es so etwas in der Bash-Version 4.2.24 (1)?
Ali Ismayilov
195
Es ist wichtig zu beachten, dass ARRAY + = ('foo') sich stark von ARRAY + = 'foo' unterscheidet, bei dem die Zeichenfolge 'foo' an den Eintrag mit der niedrigsten (?) Taste angehängt wird.
TheConstructor
8
Laut wiki.bash-hackers.org/scripting/bashchanges erschien diese Syntax erstmals in Version 3.1-alpha1.
David Yaw
39
@Jas: Um auf das gesamte Array zuzugreifen , müssen Sie Folgendes verwenden: ${myarray[@]}Wenn Sie auf eine Array-Variable verweisen, als wäre sie ein Skalar, entspricht dies dem Zugriff auf das Element 0. mit anderen Worten: $myarrayist das gleiche wie ${myarray[0]}.
mklement0
76

Wie Dumb Guy betont, ist es wichtig zu beachten, ob das Array bei Null beginnt und sequentiell ist. Da Sie nicht zusammenhängende Indizes zuweisen und nicht festlegen können, ${#array[@]}ist dies nicht immer das nächste Element am Ende des Arrays.

$ 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

So erhalten Sie den letzten Index:

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

Das zeigt, wie man das letzte Element eines Arrays erhält. Sie werden dies oft sehen:

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

Wie Sie sehen können, ist dies nicht das letzte Element, da es sich um ein spärliches Array handelt. Dies funktioniert jedoch sowohl bei spärlichen als auch bei zusammenhängenden Arrays:

$ echo ${array[@]: -1}
i
Bis auf weiteres angehalten.
quelle
3
Tolles Zeug; Ich wusste nie, dass die Syntax zum Extrahieren von Teilzeichenfolgen auch auf Arrays angewendet werden kann. Die durch Versuch und Irrtum bestimmten Regeln lauten (Bash 3.2.48): ${array[@]: start[:count]}Gibt die Anzahl der Elemente zurück. oder, falls nicht anders angegeben, alle verbleibenden Elemente. ab folgendem elem: - Wenn start> = 0: vom elem. dessen Index ist> = Start. - Wenn Start <0: vom Element. dessen Index ist (letzter Array-Index + 1) - abs (Start); CAVEAT: Wenn abs (start)> (letzter Array-Index + 1), wird eine Nullzeichenfolge zurückgegeben. Wenn count angegeben ist, werden so viele Elemente zurückgegeben, auch wenn ihre Indizes von Anfang an nicht zusammenhängend sind.
mklement0
3
@mklement: In Bash 4.2 können Sie negative Array-Indizes verwenden, um auf Elemente zuzugreifen, die ab dem Ende des Arrays zählen. ${array[-1]}
Bis auf weiteres angehalten.
Das ist gut zu wissen, danke. OS X (ab 10.8.2) verwendet immer noch 3.2.48, und stackoverflow.com/questions/10418616/… sagt mir leider, dass "Apple eine ziemlich alte Version von Bash verwendet, da sie keinen lizenzierten Code liefern unter GPL3. "
mklement0
49
$ declare -a arr
$ arr=("a")
$ arr=("${arr[@]}" "new")
$ echo ${arr[@]}
a new
$ arr=("${arr[@]}" "newest")
$ echo ${arr[@]}
a new newest
Ghostdog74
quelle
8
schön für Bash-Versionen, die die Semantik von + = Operator nicht unterstützen, erklärt durch e-t172
akostadinov
12
Eine gute abwärtskompatible Lösung. Beachten Sie jedoch, dass vorhandene Elemente, wenn sie Leerzeichen enthalten, in mehrere Elemente aufgeteilt werden. Verwenden arr=("${arr[@]}" "new")Sie diese
Option,
1
Dies kann auch verwendet werden, um vor das Array zu schieben, was genau das ist, was ich brauche.
Tomáš Zato - Wiedereinsetzung Monica
29

Wenn Ihr Array immer sequentiell ist und bei 0 beginnt, können Sie Folgendes tun:

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

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

Wenn Sie versehentlich Leerzeichen zwischen dem Gleichheitszeichen verwenden:

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

Dann erhalten Sie eine ähnliche Fehlermeldung wie:

array_name[3]: command not found
Blöder Kerl
quelle
5
Ja, das können Sie, aber die +=Syntax (siehe Antwort von @ e-t172) ist (a) einfacher und (b) funktioniert auch mit Arrays, die nicht zusammenhängend sind und / oder nicht mit 0 beginnen.
mklement0
Ehrlich gesagt funktioniert diese Lösung (für mich) besser als das "+ =", da bei letzterem die Länge manchmal falsch ist (erhöht sich um zwei, wenn ein Element hinzugefügt wird) ... also bevorzuge ich diese Antwort! :)
Pierpaolo Cira
Dies funktioniert auch in früheren Versionen von Bash, bevor sie +=hinzugefügt wurden, z. B. Version 2
Zoey Hewll
1
Dies funktioniert auch, wenn Ihre Elemente Leerzeichen enthalten - $arr += ($el)schien die Zeichenfolge durch Leerzeichen zu teilen und jedes der Elemente hinzuzufügen.
Max
5

Mit einem indizierten Array können Sie Folgendes erreichen:

declare -a a=()
a+=('foo' 'bar')
Grégory Roche
quelle