Aggiungi un nuovo elemento a un array senza specificare l'indice in Bash


Risposte:


1540

Si C'è:

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

Manuale di riferimento di Bash :

Nel contesto in cui un'istruzione di assegnazione assegna un valore a una variabile di shell o a un indice di array (vedere Array), è possibile utilizzare l'operatore '+ =' per aggiungere o aggiungere al valore precedente della variabile.


21
Funziona bene con bash 3.2.48 (OS X 10.8.2). Si noti che ARRAYè solo un segnaposto per un nome di variabile effettivo. Anche se gli indici dell'array non sono sequenziali, l'aggiunta con +=verrà semplicemente assegnata all'indice più alto + 1.
mklement0

3
C'è qualcosa del genere nella versione 4.2.24 (1) di bash?
Ali Ismayilov,

195
È importante notare che ARRAY + = ('foo') è molto diverso da ARRAY + = 'foo', che aggiunge la stringa 'foo' alla voce con il tasto più basso (?).
TheConstructor

8
Secondo wiki.bash-hackers.org/scripting/bashchanges , questa sintassi è apparsa per la prima volta nella versione 3.1-alpha1.
David Yaw,

39
@Jas: per accedere all'intero array, è necessario utilizzare ${myarray[@]}- fare riferimento a una variabile di array come se fosse uno scalare equivale ad accedere al suo elemento 0; in altre parole: $myarrayè uguale a ${myarray[0]}.
mklement0,

76

Come sottolinea Dumb Guy , è importante notare se l'array inizia da zero ed è sequenziale. Poiché è possibile effettuare assegnazioni e non impostare indici non contigui ${#array[@]}non è sempre l'elemento successivo alla fine dell'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

Ecco come ottenere l'ultimo indice:

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

Ciò illustra come ottenere l'ultimo elemento di un array. Vedrai spesso questo:

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

Come puoi vedere, poiché abbiamo a che fare con una matrice sparsa, questo non è l'ultimo elemento. Funziona su matrici sparse e contigue, sebbene:

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

3
Roba fantastica; non ho mai saputo che la sintassi di estrazione della sottostringa potesse essere applicata anche alle matrici; le regole, determinate da tentativi ed errori, sono (bash 3.2.48): ${array[@]: start[:count]}resi conteggi elems. o, se non specificato, tutti gli elementi rimanenti . a partire dal seguente elem .: - Se start> = 0: dal elem. il cui indice è> = inizio. - Se inizia <0: dall'elem. il cui indice è (ultimo indice dell'array + 1) - abs (inizio); CAVEAT: se abs (inizio)> (ultimo indice dell'array + 1), viene restituita una stringa nulla. Se viene specificato count, vengono restituiti molti elementi, anche se i loro indici non sono contigui dall'inizio.
mklement0

3
@mklement: in Bash 4.2, è possibile utilizzare sottoscrizioni di array negative per accedere agli elementi che contano dalla fine dell'array. ${array[-1]}
In pausa fino a nuovo avviso.

Buono a sapersi, grazie. OS X (a partire da 10.8.2) utilizza ancora 3.2.48, e stackoverflow.com/questions/10418616/... mi dice che, purtroppo, "Apple usa piuttosto una vecchia versione di Bash, in quanto non spediscono il codice che viene concesso in licenza sotto GPL3 ".
mklement0

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

8
bello per le versioni bash che non supportano la semantica di + = operatore spiegato da e-t172
akostadinov

12
una buona soluzione compatibile con le versioni precedenti, ma attenzione che se uno degli elementi esistenti contiene spazi, essi saranno suddivisi in più elementi; usa arr=("${arr[@]}" "new")se hai degli elementi con degli spazi
kbolino

1
Questo può anche essere usato per spingere di fronte l'array, che è proprio quello di cui ho bisogno.
Tomáš Zato - Ripristina Monica l'

29

Se l'array è sempre sequenziale e inizia da 0, è possibile farlo:

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

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

Se si utilizzano inavvertitamente spazi tra il segno uguale:

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

Quindi riceverai un errore simile a:

array_name[3]: command not found

5
Sì, puoi, ma la +=sintassi (vedi la risposta di @e-t172) è (a) più semplice e (b) funziona anche con array non contigui e / o che non iniziano con 0.
mklement0

Onestamente questa soluzione (per me) funziona meglio di "+ =", perché con quest'ultima la lunghezza a volte è sbagliata (aumenta di due quando si aggiunge un elemento) ... quindi preferisco questa risposta! :)
Pierpaolo Cira,

Funziona anche con le versioni precedenti di bash, prima che +=fosse aggiunta, ad es. Versione 2
Zoey Hewll,

1
Questo funziona anche quando i tuoi elementi hanno spazi in essi - $arr += ($el)sembra dividere la stringa per spazio e aggiungere ciascuno degli elementi.
Max

5

Con un array indicizzato, puoi fare qualcosa del genere:

declare -a a=()
a+=('foo' 'bar')
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.