Une compilation de documentations   { en , fr }

Introduction aux tableaux en bash

Étiquettes:
Créé en:
Dernière modification:
Auteur:
Xavier Béguin

Création d'un tableau

La création d'un tableau indicé peut se faire simplement par initialisation, en fournissant ses élements entre parenthèses :

tableau_indi=("un" "deux" "trois" "quatre")

Les indices sont ici assignés automatiquement, en commençant par zéro. On peut aussi l'initialiser avec des indices imposés :

tableau_indi=("fry" "leela" [42]="bender" "flexo")

Dans cet exemple, l'indice 0 vaut fry, le 1 leela, le 42 bender et le 43 flexo (les valeurs des autres indices sont la chaîne vide).

Les tableaux associatifs peuvent être créés de la même manière, mais une clef doit bien sûr être précisée pour chaque élément :

tableau_asso=(['un']="one" ['deux']="two" ['trois']="three")

Attention : l'initialisation d'un tableau ne change pas sa nature. S'il a été créé en tant que tableau indicé, puis initialisé comme un tableau associatif de même nom, cette nouvelle initialisation ne provoquera pas d'erreur, mais le tableau sera toujours considéré comme indicé, et non associatif, et il ne se comportera pas comme vous pourriez vous y attendre. Une déclaration explicite, présentée ci-dessous, évite ce problème.

Un tableau peut être créé de façon explicite à l'aide du mot-clef declare (ou, dans une fonction, du mot-clef équivalent local), suivi de l'option -a pour un tableau indicé, et -A pour un tableau associatif :

declare -a tableau_indi
declare -A tableau_asso

Le tableau peut aussi être initialisé en même temps qu'il est déclaré :

  • pour un tableau indicé, on écrira donc :
    declare -a tableau_indi=("un" "deux" "trois" "quatre")
    
  • et pour un tableau associatif :
    declare -A tableau_asso=(['un']="one" ['deux']="two" ['trois']="three")
    

Un tableau indicé peut également être créé implicitement en assignant une valeur à un élément indicé (voir plus bas).

Les tableaux peuvent aussi être déclarés en lecture seule grâce à l'option -r de declare ou du mot-clef readonly en remplacement de declare. Ces deux lignes produisent dont le même résultat :

declare -r -a tableau_indi_ro=("un" "deux" "trois" "quatre")
readonly -a tableau_indi_ro=("un" "deux" "trois" "quatre")

La modification d'un tableau en lecture seule provoquera une erreur avec le message variable en lecture seule.

Affichage du tableau

L'affichage de l'ensemble d'un tableau se fait avec la syntaxe "${montableau[*]}", ou "${montableau[@]}". Ces syntaxes diffèrent uniquement lorsqu'elles sont utilisées entre guillemets doubles. Leur différence est identique à celle des variables spéciales $@ et $* du shell. Pour citer le manuel de bash :

(...) entre guillemets doubles, ${nom[*]} se développe en un seul mot contenant les valeurs de chaque élément du tableau séparées par le premier caractère de la variable spéciale IFS et ${nom[@]} développe chaque élément de nom en un mot distinct.

Pour reprendre les exemples de tableaux déclarés plus haut :

$ declare -a tableau_indi=("un" "deux" "trois" "quatre")
$ echo "${tableau_indi[@]}"
un deux trois quatre
$ declare -A tableau_asso=(['un']="one" ['deux']="two" ['trois']="three")
$ echo "${tableau_asso[@]}"
one two three

L'utilisation des accolades est nécessaire pour éviter les conflits avec les développements de chemin (dans lesquels les crochets ont une signification spéciale).

Affichage des clefs d'un tableau

Il est possible d'obtenir la liste des clefs d'un tableau à l'aide de la syntaxe ${!tableau[@]} :

  • dans le cas d'un tableau associatif, on obtient bien ses clefs :
    $ declare -A tableau_asso=(['un']="one" ['deux']="two" ['trois']="three")
    $ echo "${!tableau_asso[@]}"
    un deux trois
    
  • dans le cas d'un tableau indicé, on obtient ses indices :
    $ declare -a tableau_indi=("un" "deux" "trois" "quatre")
    $ echo "${!tableau_indi[@]}"
    0 1 2 3
    
    Ceci permet de vérifier les indices assignés aux valeurs lors de l'initialisation du tableau. Pour reprendre notre exemple d'assignation utilisé plus tôt :
    $ declare -a tableau_indi("fry" "leela" [42]="bender" "flexo")
    $ echo "${!tableau_indi[@]}"
    0 1 42 43
    

Lecture d'un élément

La lecture d'un élément se fait selon une syntaxe du type tableau[clef], mais nécessite toujours les accolades, ce sera donc ${tableau[clef]} :

$ montableau=("un" "deux" "trois" "quatre")
$ echo "${montableau[2]}"
trois
$ tab_asso=(['un']="one" ['deux']="two" ['trois']="three")
$ echo "${tab_asso["deux"]}"
two

Pour les tableaux indicés, un indice négatif correspond à un indice commençant à l'indice maximal du tableau plus un (le dernier élément est donc -1).

$ tableau_indi=("fry" "leela" [42]="bender" "zoidberg" "flexo")
$ echo "Why not ${tableau_indi[-2]} ?"
Why not zoidberg ?

Attention, si aucun indice n'est fourni pour le tableau, on accède à l'indice 0 :

$ montableau=("un" "deux" "trois" "quatre")
$ echo $montableau
un
$ echo ${montableau[0]}
un

Modification d'un élément

Un élément peut être assigné selon la syntaxe tableau[indice]=valeur :

$ tab[1]="uno"
$ echo ${tab[1]}
uno

Si le tableau tab ci-dessus n'existe pas, il sera créé comme un tableau indicé.

Il n'est pas possible de créer un tableau associatif en lui assignant un élément car l'assignation ne crée que des tableaux indicés (la clef fournie est ignorée et l'indice utilisé est 0) :

$ tab["couleur"]="jaune"
$ echo "${!tab[*]}"  # (affiche les clefs du tableau)
0
$ echo "${tab[0]}"
"jaune"

Un tableau associatif doit donc impérativement être déclaré explicitement avant l'assignation d'un élément :

$ declare -A tab
$ tab["couleur"]="jaune"
$ echo "${!tab[*]}"
couleur
$ echo "${tab["couleur"]}"
jaune

On peut aussi combiner la déclaration et l'initialisation du tableau associatif (comme décrit plus haut dans la section « Création d'un tableau ») :

$ declare -A tab_asso=(["couleur"]="jaune")
$ echo ${tab_asso["couleur"]}
jaune

Notez que si le tableau est en lecture seule, cette opération génère une erreur :

$ declare -ar tableau_indi_ro=("arthur" "trillian")
$ tableau_indi_ro[42]="h2g2"
bash: tableau_indi_ro : variable en lecture seule

Obtention de la taille d'un tableau

Le nombre d'éléments contenus dans un tableau (donc sa taille) s'obtient avec la syntaxe ${#tableau[@]} :

$ declare -a tableau_indi=("un" "deux" "trois" "quatre")
$ echo "${#tableau_indi[@]}"
4

$ declare -A tableau_asso=(['un']="one" ['deux']="two" ['trois']="three")
$ echo "${#tableau_asso[@]}"
3

Attention, les indices d'un tableau indicé ne représentent pas simplement des positions dans le tableau mais plutôt des clefs numériques (qui peuvent être choisies arbitrairement). La taille d'un tableau indicé ne correspond donc pas forcément au plus grand indice augmenté de un :

$ declare -a tableau_indi("fry" "leela" [42]="bender" "flexo")
$ echo ${#tableau_indi[@]}
4

Destruction d'un élément de tableau

On peut supprimer un élément d'un tableau avec la commande unset tableau[indice] :

  • exemple avec un tableau indicé :
    $ declare -a tableau_indi=("un" "deux" "trois" "quatre")
    $ echo ${tableau_indi[@]}
    un deux trois quatre
    $ unset tableau_indi[1]
    $ echo ${!tableau_indi[@]}
    0 2 3
    $ echo ${tableau_indi[@]}
    un trois quatre
    
  • le fonctionnement de unset est sensiblement le même avec un tableau associatif :
    $ declare -A tableau_asso=(['un']="one" ['deux']="two" ['trois']="three")
    $ echo ${tableau_asso[@]}
    one two three
    $ unset tableau_asso['deux']
    $ echo ${!tableau_asso[@]}
    un trois
    $ echo ${tableau_asso[@]}
    one three
    

Destruction d'un tableau entier

Comme pur toute variable du shell, la commande unset permet aussi de détruire tout un tableau. On peut le référencer en lui passant son nom, ou une des formes nom[*] ou nom[@].

Ainsi, en supposant un tableau de nom tableau, les trois lignes suivantes sont équivalentes :

  • unset tableau
  • unset tableau[@]
  • unset tableau[*]

On peut vérifier le bon fonctionnement de unset en utilisant declare -p (qui affiche la valeur d'une variable sous une forme qui permet sa déclaration) pour vérifier l'existence d'une variable :

$ declare -a tableau_indi=("un" "deux" "trois" "quatre")
$ declare -p tableau_indi
declare -a tableau_indi=([0]="un" [1]="deux" [2]="trois" [3]="quatre")
$ unset tableau_indi
$ declare -p tableau_indi
bash: declare: tableau_indi : non trouvé