====== script bash : Tableaux ====== * Objet : script bash : Tableaux * Niveau requis : {{tag>débutant avisé}} * Commentaires : FIXME * Débutant, à savoir : [[:doc:systeme:commandes:le_debianiste_qui_papillonne|Utiliser GNU/Linux en ligne de commande, tout commence là !.]] :-) * Suivi : * Création par [[user>Hypathie]] le 18/03/2014 * Testé par [[user>Hypathie]] Juin 2014 * Commentaires sur le forum : [[https://debian-facile.org/viewtopic.php?pid=142812#p142812 | Lien vers le forum concernant ce tuto]] ((N'hésitez pas à y faire part de vos remarques, succès, améliorations ou échecs !)) Contributeurs, les FIXME sont là pour vous aider, supprimez-les une fois le problème corrigé ou le champ rempli ! **Nota : Les autres wiki :** * [[doc:programmation:shells:debuter-avec-les-scripts-shell-bash]] * [[doc:programmation:shells:script-bash-variables-arguments-parametres|script-bash-variables-arguments-parametres]] * [[doc:programmation:shells:script-bash-detail-sur-les-parametres-et-les-boucles|modification de variable et de paramètre]] * [[doc:programmation:shells:script-bash-enchainement-de-commandes-et-etat-de-sortie|script-bash-enchainement-de-commandes-et-etat-de-sortie]] * [[doc:programmation:shells:script-bash-etat-de-sorie-et-les-tests|script-bash-etat-de-sortie-et-les-tests]] * ;-) * [[doc:programmation:shells:fonction|script-bash-les-fonctions]] ===== Utiliser des tableaux ===== Les tableaux ne sont pas spécifiés par POSIX.\\ Les tableaux indexés unidimensionnels sont pris en charge en utilisant la syntaxe et la sémantique similaire à la plupart des shells comme Korn.\\ Pour plus détails voir : [[http://wiki.bash-hackers.org/syntax/arrays]] ==== Définitions ==== - Un tableau est une variable contenant d'autres variables rangée en mémoire les unes à la suite des autres. - Un tableau est unidimensionnel. - Chaque variable contenue dans le tableau est nommée par le numéro de sa case et affectée d'une valeur (le contenu de sa case). - L'indice est le numéro de la case. - Appeler l'indice d'une case permet d'appeler la valeur correspondante à cette case : on dit "déréférencer l'élément du tableau". >Les termes "matrice", "vecteur" ou "table" sont parfois synonymes de "tableau";\\ "l'indice" est parfois appelé "index". >Les cases d'un tableau peuvent ne pas être consécutives. ==== Quatre méthodes pour créer un tableau ==== * Avec la commande ''declare'' et l'option ''-a'' : declare -a nom-tableau=(valeur0 valeur1 valeur2 ...) * Directement : nom-tableau(valeur0 valeur1 ...) * Autre syntaxe : nom-tableau=([indice0]=valeur0 [indice1]=valeur1 ...) Si l'on souhaite créer un tableau avec des cases "manquantes",\\ c'est-à-dire, donnée à la valeur de certaines cases, un indice qui n'est pas le numéro qui suit directement, il faut utiliser alors cette méthode. * Avec la commande ''read'' :\\ les valeurs sont données via le terminal par l'utilisateur. read -a nom-tableau === Exemple === #!/bin/bash array=([2]=nom1 nom2 [6]=nom3) # (1) echo ${!array[@]} tb=(nom1 nom2 nom3) echo ${!tb[*]} declare -a tab=(nom1 nom2 nom3) echo ${!tab[@]} read -a tableau echo ${!tableau[*]} >(1) On voit là que si l'on n'affecte pas un indice à une case, >elle prend le numéro suivant de l'indice précédemment déclaré. ./mon-script 2 3 6 0 1 2 0 1 2 nom nom nom nom nom 0 1 2 3 4 >''2 3 6'' : la première valeur a l'indice 2 ; la deuxième a l'indice 3 ; la troisième a l'indice 6. > >''0 1 2'' : Il y a une valeur dans les cases d'indice 0, d'indice 1, d'indice 2. > >''0 1 2'' : idem > >''0 1 2 3 4'' : Sans indice donné manuellement, les indices attribués aux valeurs suivent l'ordre des entiers naturels en __commençant à zéro__. ==== Récupération de valeur(s) ==== === Valeur d'une case === ${nom-tableau[indice]} === Valeurs de toutes les cases === Tous les éléments d'un tableau sont accessibles avec chacune de ces deux syntaxes : ${nom-tableau[*]} ${nom-tableau[@]} === Nombre d'éléments d'un tableau === Le nombre d'éléments d'un tableau est accessible par chacune de ces deux syntaxes : ${#nomtableau[*]} ${#nomtableau[@]} === n° des cases utilisées === Il est possible de récupérer le numéro des cases qui ont été utilisées dans un tableau,\\ Pour ce faire, la syntaxe est : ${!nom-tableau[*]} === Concaténer deux tableaux en un seul === Concaténer dans un seul tableau nouvellement initialisé les cases de tableaux existants : nom-tableau3=("${nom-d-un-tableau1[@]}" "${nom-d-un-tableau2}" ...) ===== Exemple ===== #!/bin/bash # méthodes 1 : tab=(salade_verte, savoyarde, niçoise,) echo ${tab[0]} echo ${tab[1]} echo ${tab[2]} echo "Nous avons dit : ${tab[*]} c-à-d ${#tab[@]} choix." echo " " #méthode 2: declare -a tableau=(entrecôte, cabillaud, fruits_de_mer, frites, gratin_dauphinois) echo ${tableau[0]} echo ${tableau[1]} echo ${tableau[2]} echo "Nous avons dit : ${tableau[*]} c-à-d ${#tableau[@]} choix de plus." echo " " #méthode 3 : t=( [0]=glace, [1]=tarte-maison, [2]=yahourt, [3]=pudding, [4]=fruits,) echo ${t[0]} echo ${t[1]} echo ${t[2]} echo ${t[3]} echo ${t[4]} echo "Nous avons dit : ${t[*]} c-à-d ${#t[@]} choix de plus." #méthode 4 par la lecture : echo "Écrivez ce qu'il manque à cette liste, svp ? : " read -a tb echo "vous auriez souhaité : ${tb[*]} " echo "la liste est maintenant : ${tab[*]} ${tableau[*]} ${t[*]} ${tb[*]}" declare -a arrayconcat=("${tab[@]}" "${tableau[@]}" "${t[@]}" "${tb[@]}") echo "Cela nous fait une liste de ${#arrayconcat[@]} choix !" ===== Nombres entiers ===== Si l'on souhaite créer un tableau d'entiers, on utilise la commande ''declare'' avec l'option ''-ai''.\\ (l'ordre des options n'a pas d'importance.) Les syntaxes précédentes peuvent aussi être utilisées : #!/bin/bash declare -ai tab=(18 2 -2) echo ${tab[@]} tableau=([0]=2 [2]=4 [4]=6) echo ${tableau[@]} tb=(1 2 3 4) echo ${tb[@]} read -a t echo ${t[@]} ./mon-script 18 2 -2 2 4 6 1 2 3 4 5 6 7 8 9 5 6 7 8 9 ===== Ajout suppression ===== * Pour ajouter un élément à un tableau : ''tableau[${#tableau[*]}]=element'' #!/bin/bash tableau=( bleu jaune rouge ) echo ${#tableau[*]} tableau[${#tableau[*]}]=couleurs echo ${tableau[*]} 3 bleu jaune rouge couleurs * Pour ajouter un élément au début d'un tableau : ''tableau=( element ${tableau[*]} )'' #!/bin/bash tab=( noir blanc ) echo ${tab[*]} tab=( colorless ${tab[*]} ) echo ${tab[*]} noir blanc colorless noir blanc * pour supprimer un tableau : ''unset nom-tableau'' * pour supprimer la case d'un tableau : ''unset nom-tableau[indice] ...'' ===== Tableau associatif ===== Un tableau associatif est un tableau uni-dimentionnel à ceci près que les index sont des chaînes de caractères.\\ Il en va de même que précédemment : * l'indice se récupère ainsi : ''${!tableau[@]}''; * la valeur se récupère ainsi : ''${tableau[@]}''; #!/bin/bash declare -A eleves=([secondeA]=30 [secondeB]=29) for i in "${!eleves[@]}" do echo "l'indice ici nom de la classe est : $i" echo "le nombre d'élèves est ici la valeur : ${eleves[$i]}" done ./mon-script l'indice ici nom de la classe est : secondeB le nombre d'élèves est ici la valeur : 29 l'indice ici nom de la classe est : secondeA le nombre d'élèves est ici la valeur : 30 * Il faut utiliser ''@'' (et non ''*'') pour que la boucle permette d'afficher **chacune des valeurs**. ===== Conclusion ===== ==== Récapitulatif ==== #!/bin/bash tab=( rouge vert bleu) echo ${tab[1]} echo ${tab[@]} tab[1]="orange" echo ${tab[1]} echo ${tab[@]} echo $tab # $tab est un équivalment de $tab0 : il affichera le première élément echo ${tab[@]} # affiche tous les éléments de même ${tab[*]} echo ${#tab[@]} # pour avoir la longueur (nombres d'éléments dans le tableau): # ${tab[@]}-1 (moins un car on commence à zéro! tab[8]="vert" # nlle affectation sur tab[8] echo ${!tab[@]} # ! avoir la liste des indices du tableau echo ${tab[@]} for i in ${!tab[*]} ; do echo $i : ${tab[$i]} done ==== Se creuser un peu les méninges ==== Comparez ses méthodes pour associer à l'affichage, un à un , deux éléments du retours : * Avec un tableau : #!/bin/bash tableau=([1]=a [2]=b [3]=c) for var in "${!tableau[@]}" ; do echo "$var : ${tableau[$var]}" done * Avec les paramètres de position et une boucle : set a b c n=1 for v in $@ do echo "$n: $v" ((n++)) done **Merci à enikar pour ce script et cette réflexion sur IRC** 8-) Mais aussi, après avoir vu [[doc:programmation:shells:fonction|script-bash-les-fonctions]] avec le script de captnfab : [[doc:programmation:shell:avancee#les-fonctions|Fonctionnalités avancées du Shell: Les fonctions]] ==== Une astuce ==== Lister avec numérotation tous les fichiers d'un répertoire #!/bin/bash directory=(/*) # (1) for i in ${!directory[@]} ; do echo "$i : ${directory[$i]}" # (2) done >(1) : Tableau composé par les chemins de dossiers et fichiers depuis la racine. >(2) : Pour afficher tous les éléments du tableau. ===== La suite c'est ici ===== * [[doc:programmation:shells:fonction|script-bash-les-fonctions]]