Chapitre 12. Tableaux

Table des matières

12.1. Tableaux classiques
12.1.1. Définition et initialisation
12.1.2. Opérations sur un élément de tableau classique
12.1.3. Opérations sur un tableau classique
12.2. Tableaux associatifs
12.2.1. Définition et initialisation
12.2.2. Opérations sur un élément de tableau associatif
12.2.3. Opérations sur un tableau associatif

Moins utilisés que les chaînes de caractères ou les entiers, bash intègre les tableaux classiques et les tableaux associatifs. Les éléments des premiers sont indicés par des entiers, tandis que les éléments des seconds sont indexés par des chaînes de caractères.

Les tableaux classiques et associatifs sont monodimensionnels. Il n'y a pas de taille maximale fixée pour un tableau

12.1. Tableaux classiques

12.1.1. Définition et initialisation

  • Pour créer un ou plusieurs tableau classiques vides, on utilise généralement l'option -a de la commande interne declare :

       declare -a nomtab ...

    Le tableau nomtab est simplement créé mais ne contient aucune valeur : le tableau est défini mais n'est pas initialisé.

  • Pour lister les tableaux classiques définis : declare -a

    declare -a BASH_ARGC=([0]="0")
    declare -a BASH_ARGV=()
    declare -a BASH_COMPLETION_VERSINFO=([0]="2" [1]="11")
    declare -a BASH_LINENO=()
    declare -a BASH_REMATCH=()
    declare -a BASH_SOURCE=()
    declare -ar BASH_VERSINFO=([0]="5" [1]="1" [2]="4" [3]="1" [4]="release" [5]="x86_64-pc-linux-gnu")
    declare -a DIRSTACK=()
    declare -a FUNCNAME
    declare -a GROUPS=()
    declare -a PIPESTATUS=([0]="0")
    $
    

  • Pour désigner un élément d'un tableau classique, on utilise la syntaxe : nomtab[indice]

    $ declare -a tab 	=> définition du tableau tab
    $
    $ read tab[1] tab[3]
    coucou bonjour
    $
    $ tab[0]=hello
    $
    
  • Pour définir et initialiser un tableau classique : declare -a nomtab=( val0 val1 ... )

    Comme en langage C, l'indice d'un tableau classique débute toujours à 0 et sa valeur maximale est celle du plus grand entier positif représentable dans ce langage (bash a été écrit en C). L'indice peut être une expression arithmétique [cf. Chapitre 11, Entiers et expressions arithmétiques].

    Il n'est pas obligatoire d’utiliser la commande interne declare pour créer un tableau classique, il suffit d'initialiser un de ses éléments :

    $ array[3]=bonsoir   => création du tableau array avec
    $                    => initialisation de l’élément d’indice 3
    

    Trois autres syntaxes sont également utilisables pour initialiser globalement un tableau classique :

    • nomtab=(val0 val1 ...)

    • nomtab=( [indice]=val ... )

      $ arr=([1]=coucou [3]=hello)
      $
      
    • l'option -a de la commande interne read ou readonly. Chaque mot saisi devient un élément du tableau classique :

      $ read -a tabmess
      bonjour tout le monde
      $
      
  • Pour créer un tableau classique en lecture seule, on utilise les options –ra.

    $ declare -ra tabconst=( bonjour coucou salut )	    => tableau en lecture seule
    $
    $ tabconst[1]=ciao
    bash: tabconst : variable en lecture seule
    $
    
  • Pour afficher les valeurs et attributs d’un tableau classique, on utilise la syntaxe : declare –p tab …

    $ declare -p tabconst
    declare -ar tabconst=([0]="bonjour" [1]="coucou" [2]="salut")
    $
    

12.1.2. Opérations sur un élément de tableau classique

  • Valeur d'un élément d'un tableau :

    On obtient la valeur d'un élément d'un tableau à l’aide la syntaxe : ${nomtab[indice]}

    bash calcule d'abord la valeur de l'indice puis l'élément du tableau est remplacé par sa valeur.

    Il est possible d'utiliser :

    • toute expression arithmétique valide de la commande interne (( pour calculer l'indice d'un élément

      $ echo ${tabmess[1]}
      tout
      $
      $ echo ${tabmess[RANDOM%4]}     => ou bien : ${tabmess[$((RANDOM%4))]}
      monde
      $
      $ echo ${tabmess[1**2+1]}
      le
      $
    • une variable contenant un entier

      $ a=3
      $ echo ${tabmess[a]}
      monde
      $
      

    Il est possible d'utiliser une valeur négative comme indice : dans ce cas, la valeur -1 permettra d’accéder au dernier élément du tableau, la valeur -2 à l’avant-dernier élément, etc.

    $ declare -p tabmess 
    declare -a tabmess=([0]="bonjour" [1]="tout" [2]="le" [3]="monde")
    $ 
    $ echo ${tabmess[-1]}
    monde
    $
    $ echo ${tabmess[-4]}
    bonjour
    $ 
    $ echo ${tabmess[-5]}
    bash: tabmess: mauvais indice de tableau
    $
    

    Lorsqu'un nom de tableau est présent sans indice dans une chaîne de caractères ou une expression, bash l’interprète comme élément d'indice 0.

    $ echo $tabmess
    bonjour
    $
    

    Réciproquement, une variable non préalablement définie comme tableau peut être interprétée comme un tableau classique.

    $ var=bonjour
    $ echo ${var[0]}	=> var est interprétée comme un tableau à un seul élément
    bonjour			=>     d’indice 0
    $ var=( coucou "${var[0]}" )
    $ echo ${var[1]}	=> var est devenu un véritable tableau
    bonjour
    $
    

  • Longueur d'un élément :

    Pour obtenir la longueur d'un élément d'un tableau classique : ${#nomtab[indice]}

    $ declare -p tabmess 
    declare -a tabmess=([0]="bonjour" [1]="tout" [2]="le" [3]="monde") 
    $ 	
    $ echo ${tabmess[0]}
    bonjour
    $
    $ echo ${#tabmess[0]}
    7   => longueur de la chaîne bonjour
    $
    $ echo ${tabmess[-1]} : ${#tabmess[-1]} 
    monde : 5   		=> longueur du dernier élément de tabmess (chaine monde) 
    $
    
  • Suppression d’un élément :

    Suppression d'un ou plusieurs éléments d'un tableau classique : unset nomtab[indice] ...

  • Autres opérations :

    Les différents traitements sur les chaînes de caractères vus précédemment [cf. Chapitre 9, Chaînes de caractères § 3, 4, 5, 6] sont également applicables aux éléments d’un tableau classique.

    Modificateurs de chaîne :

       ${nomtab[indice]#modèle}     ${nomtab[indice]##modèle}

       ${nomtab[indice]%modèle}     ${nomtab[indice]%%modèle}

    Extraction d’une sous-chaîne :

       ${nomtab[indice]:ind}     ${nomtab[indice]:ind:nb}

    Remplacement de sous-chaîne :

       ${nomtab[indice]/mod/ch}     ${nomtab[indice]//mod/ch}

    Transformation majuscules/minuscules :

       ${nomtab[indice]^^}     ${nomtab[indice],,}

    $ tpers=("Jean Fontaine:20:1,72"  "Pierre Cascade:18:1,83")
    $ 
    $ echo ${tpers[1]#*:}		=> Modificateur
    18:1,83
    $
    $ echo ${tpers[0]%%:*}		=> Modificateur
    Jean Fontaine
    $
    $ echo ${tpers[1]:0:8}		=> Extraction
    Pierre C
    $ 
    $ echo ${tpers[0]/20/31}	=> Remplacement
    Jean Fontaine:31:1,72
    $
    $ echo ${tpers[0]/#72/91}  	=> Remplacement si 72 est en début de chaine 
    Jean Fontaine:20:1,72  		=>      Aucun remplacement effectué ! 
    $  
    $ echo ${tpers[0]/%72/91}	=> Remplacement si 72 est en fin de chaine  
    Jean Fontaine:20:1,91 		=>      Remplacement effectué !
    $ 
    $ echo ${tpers[0]^^}		=> Mise en majuscules
    JEAN FONTAINE:20:1,72
    $
    

    Remarque : Les syntaxes relatives à l’extraction de sous-chaines (${nomtab[indice]:ind}, ${nomtab[indice]:ind:nb}) autorisent une valeur négative pour ind. Dans ce cas, il est impératif de placer un caractère espace entre le caractère : et le caractère désignant le signe, sous peine d’obtenir un résultat erroné.

    $ echo ${tpers[0]: -4:4}	=> caractère espace entre : et -4 
    1,72 
    $ 
    

    Dans l’exemple ci-dessus, on souhaite afficher les quatre derniers caractères de la chaine contenue dans tpers[0].

12.1.3. Opérations sur un tableau classique

  • Nombre d’éléments d’un tableau classique : ${#nomtab[@]}

    Il existe plusieurs notations pour connaître le nombre d’éléments d’un tableau : ${#nomtab[*]}, ${#nomtab[@]},"${#nomtab[*]}", "${#nomtab[@]".

    Par souci d’homogénéité avec les syntaxes relatives aux autres opérations, nous utiliserons la notation : ${#nomtab[@]}

    Il est à noter que seuls les éléments initialisés sont comptés.

    $ arr=([1]=coucou  [3]=hello)
    $ echo ${#arr[@]}
    2
    $
    
  • Accès à tous les éléments d’un tableau classique : "${nomtab[@]}"

    Comme pour "$@" et "$*" [cf. Chapitre 2, Substitution de paramètres § 2.5], les syntaxes "${nomtab[*]}" et "${nomtab[@]}" n’ont pas la même signification pour le shell :

    • "${nomtab[*]}" sera remplacée par l’ensemble des éléments du tableau classique nomtab, concaténés en une seule chaîne et séparés par le premier caractère de IFS : "val0 val1 ... "

    • "${nomtab[@]}" sera remplacée par autant de chaînes qu’il y a d’éléments : "val0" "val1" ...

    $ tabPays=("Etats Unis"  France)
    $
    $ set "${tabPays[*]}"
    $ echo $#
    1			=> une seule chaîne
    $ 
    $ echo $1
    Etats Unis France
    $ 
    $ set "${tabPays[@]}"
    $ echo $#
    2			=> deux chaînes
    $ 
    $ echo $1
    Etats Unis
    $ echo $2
    France
    $
    

    Lorsque les éléments sont de simples chaînes constituées d’un seul mot, il n’y a aucune difficulté pour préserver l’intégrité de celles-ci. Cela est différent avec des chaînes composées.

    $ for p in ${tabPays[*]}
    > do
    >   echo $p
    > done
    Etats				=> l’intégrité du premier élément est rompue
    Unis
    France
    $
    

    Pour préserver l’intégrité de chaque élément, il est préférable d’utiliser la syntaxe : "${nomtab[@]}"

    $ for p in "${tabPays[@]}"
    > do
    >   echo $p
    > done
    Etats Unis			=> l’intégrité du premier élément est préservée
    France
    $
    
  • Liste de tous les indices définis : "${!nomtab[@]}"

    Il existe également plusieurs syntaxes pour obtenir la liste de tous les indices conduisant à un élément défini d’un tableau classique. Afin d’utiliser une syntaxe commune avec les tableaux associatifs, on utilisera la notation : "${!nomtab[@]}"

    $ arr=([1]=coucou  bonjour [5]=hello)
    $
    $ echo "${!arr[@]}"
    1 2 5		=> pour affecter un indice à bonjour, bash a incrémenté l’indice 
    $			=>     de l’élément précédent
    

    L’intérêt d’utiliser cette syntaxe est qu’elle permet de ne traiter que les éléments définis d’un tableau « à trous ».

    $ for i in "${!arr[@]}"
    > do
    >   echo "$i => ${arr[i]}"	=> dans l’expression ${arr[i]}, bash interprète 
    > done				=> 	directement i comme un entier
    1 => coucou
    2 => bonjour
    5 => hello
    $
    
  • Copie d’un tableau classique

    Pour copier un tableau classique tab : tabcopie=( "${tab[@]}" )

    $ tabcopy=( "${tabPays[@]}" )
    $
    $ echo "${tabcopy[@]}"
    Etats Unis France
    $
    
  • Ajout d’éléments à un tableau classique

    Pour ajouter un ou plusieurs éléments à un tableau classique tab :

    • à la fin : tab+=( val1 val2 … )

    • en tête : tab=( val0 val1 … "${tab[@]}")

    Remarque : Si le tableau est « sans trou », il est possible d’utiliser la syntaxe suivante pour ajouter un élément val à la fin du tableau : tab[${#tab[@]}]=val

    $ tab=("un 1"  "deux 2"  "trois 3")
    $ 
    $ tab+=("quatre 4" fin)		=>  ajout de deux éléments en fin de tableau
    $ 
    $ echo "${tab[@]}"
    un 1 deux 2 trois 3 quatre 4 fin
    $ 
    $ tab=(debut "zero 0" "${tab[@]}")		=> ajout de deux éléments en 
    $ 							=>      tête de tableau
    $ echo ${#tab[@]}
    7				=> nombre d’éléments du tableau
    $ echo "${tab[@]}"
    debut zero 0 un 1 deux 2 trois 3 quatre 4 fin
    $
    $ echo ${tab[5]}
    quatre 4
    $
  • Traitement uniforme des éléments d'un tableau classique

    Les opérations présentées précédemment peuvent être appliquées en une seule passe à l’ensemble des éléments d’un tableau classique.

    $ tpers=("Jean Fontaine:20:1,72"  "Pierre Cascade:18:1,83"  "Pierre Ruisseau:17:1,68")
    $ 
    $ echo ${tpers[@]##*:}
    1,72 1,83 1,68
    $ 
    $ echo ${tpers[@]//:/::}
    Jean Fontaine::20::1,72 Pierre Cascade::18::1,83 Pierre Ruisseau::17::1,68
    $ 
    $ echo ${tpers[@]/Pierre*/}	=> suppression des personnes ayant Pierre comme
    Jean Fontaine:20:1,72		=>       prénom	
    $
    $ echo ${tpers[@]^^}
    JEAN FONTAINE:20:1,72 PIERRE CASCADE:18:1,83 PIERRE RUISSEAU:17:1,68
    $ 
    $ tab=(zero un deux trois "quatre 4" cinq six)
    $ 
    $ echo ${tab[@]:2:4}		=> extraction de quatre éléments à
    deux trois quatre 4 cinq	=>      partir de l’indice 2 inclus
    $
    $ echo ${tab[@]: -4:2}          =>  extraction du quatrième élément avant la fin (trois) 
    trois quatre 4   	        =>     et du troisième élément avant la fin (quatre 4)
    $				=>     il y a un caractère espace entre : et -4 
    
  • Suppression d’un tableau classique

    Pour supprimer un ou plusieurs tableaux classiques : unset nomtab ...

    $ unset tabcopy  tab
    $