Ajouter un nouvel élément à un tableau sans spécifier l'index dans Bash

Réponses:

1540

Oui il y a:

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

Manuel de référence Bash :

Dans le contexte où une instruction d'affectation attribue une valeur à une variable shell ou à un index de tableau (voir Tableaux), l'opérateur '+ =' peut être utilisé pour ajouter ou ajouter à la valeur précédente de la variable.

Etienne Dechamps
la source
21
Cela fonctionne très bien avec bash 3.2.48 (OS X 10.8.2). Notez qu'il ne ARRAYs'agit que d'un espace réservé pour un nom de variable réel. Même si vos indices +=
matriciels
3
Y a-t-il quelque chose comme ça dans la version bash 4.2.24 (1)?
Ali Ismayilov
195
Il est important de noter que ARRAY + = ('foo') est très différent de ARRAY + = 'foo', qui ajoute la chaîne 'foo' à l'entrée avec la touche la plus basse (?).
TheConstructor
8
Selon wiki.bash-hackers.org/scripting/bashchanges , cette syntaxe est apparue pour la première fois dans la version 3.1-alpha1.
David Yaw
39
@Jas: Pour accéder à l' ensemble du tableau, vous devez utiliser ${myarray[@]}- référencer une variable de tableau comme s'il s'agissait d'un scalaire revient à accéder à son élément 0; en d'autres termes: $myarrayest le même que ${myarray[0]}.
mklement0
76

Comme le souligne Dumb Guy , il est important de noter si le tableau commence à zéro et est séquentiel. Étant donné que vous pouvez effectuer des affectations et supprimer des index non contigus, ce ${#array[@]}n'est pas toujours l'élément suivant à la fin du tableau.

$ 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

Voici comment obtenir le dernier index:

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

Cela illustre comment obtenir le dernier élément d'un tableau. Vous verrez souvent ceci:

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

Comme vous pouvez le voir, comme nous avons affaire à un tableau clairsemé, ce n'est pas le dernier élément. Cela fonctionne à la fois sur des tableaux clairsemés et contigus, cependant:

$ echo ${array[@]: -1}
i
En pause jusqu'à nouvel ordre.
la source
3
Grands trucs; n'a jamais su que la syntaxe d'extraction de sous-chaîne pouvait également être appliquée aux tableaux; les règles, déterminées par essais et erreurs, sont (bash 3.2.48): ${array[@]: start[:count]}Renvoie count elems. ou, si non spécifié, tous les elems restants . à partir de l'elem suivant: - Si start> = 0: à partir de l'elem. dont l'index est> = start. - Si départ <0: depuis l'elem. dont l'indice est (dernier indice du tableau + 1) - abs (début); CAVEAT: si abs (début)> (dernier index du tableau + 1), une chaîne nulle est retournée. Si count est spécifié, autant d'éléments sont retournés, même si leurs indices ne sont pas contigus depuis le début.
mklement0
3
@mklement: Dans Bash 4.2, vous pouvez utiliser des indices de tableau négatifs pour accéder aux éléments comptant à partir de la fin du tableau. ${array[-1]}
pause jusqu'à nouvel ordre.
C'est bon à savoir, merci. OS X (à partir de 10.8.2) utilise toujours la version 3.2.48, et stackoverflow.com/questions/10418616/… me dit que, malheureusement, "Apple utilise une assez ancienne version de Bash, car ils ne livrent pas de code sous licence sous GPL3. "
mklement0
49
$ declare -a arr
$ arr=("a")
$ arr=("${arr[@]}" "new")
$ echo ${arr[@]}
a new
$ arr=("${arr[@]}" "newest")
$ echo ${arr[@]}
a new newest
ghostdog74
la source
8
agréable pour les versions bash qui ne prennent pas en charge la sémantique de l'opérateur + = expliquée par e-t172
akostadinov
12
une bonne solution rétrocompatible, mais attention, si l'un des éléments existants contient des espaces, ils seront divisés en plusieurs éléments; à utiliser arr=("${arr[@]}" "new")si vous avez des éléments contenant des espaces
kbolino
1
Cela peut également être utilisé pour pousser devant la baie, ce dont j'ai besoin.
Tomáš Zato - Rétablir Monica
29

Si votre tableau est toujours séquentiel et commence à 0, vous pouvez le faire:

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

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

Si vous utilisez par inadvertance des espaces entre le signe égal:

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

Ensuite, vous recevrez une erreur similaire à:

array_name[3]: command not found
Dumb Guy
la source
5
Oui, vous pouvez, mais la +=syntaxe (voir la réponse de @ e-t172) est (a) plus simple, et (b) fonctionne également avec des tableaux non contigus et / ou ne commençant pas par 0.
mklement0
Honnêtement, cette solution (pour moi) fonctionne mieux que le "+ =", car avec ce dernier la longueur est parfois fausse (augmente de deux lors de l'ajout d'un élément) ... donc je préfère cette réponse! :)
Pierpaolo Cira
Cela fonctionne également dans les versions antérieures de bash, avant d' +=être ajouté, par exemple la version 2
Zoey Hewll
1
Cela fonctionne également lorsque vos éléments contiennent des espaces - ils $arr += ($el)semblent diviser la chaîne par espace et ajouter chacun des éléments.
Max
5

Avec un tableau indexé, vous pouvez faire quelque chose comme ceci:

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