Quitter le forum et retourner au site

Bash et les tableaux

Vous avez un didactiel ou une astuce particulière concernant un logiciel, partagez votre expérience dans cette partie.
Avatar de l’utilisateur
Ennoia
Messages : 138
Inscription : jeu. 29 mai 2008, 13:09
Distribution : ArchLinux
Niveau : Indépendance et débugage
Localisation : Oberentzen

Bash et les tableaux

Message par Ennoia »

Contexte

Le but a été de générer une liste des paquets installés. Malheureusement dans cette liste étaient inclus des paquets du système de base ou du groupe xfce dont je n'avais pas besoin du détail. Je pouvais générer des listes séparées, restait donc à en comparer les éléments et à en supprimer certains. Et en on arrive aux tableaux.

Manipulation de base

Création du tableau

Code : Tout sélectionner

ARRAY=( a aa b bb c cc d dd abcd )
Affichage de tous les éléments

Code : Tout sélectionner

echo "Le contenu du tableau est : ${ARRAY[@]}"
Nombre d’éléments du tableau

Code : Tout sélectionner

echo "le tableau contient ${#ARRAY[@]} élément(s)"
Affichage d'un élément

Code : Tout sélectionner

echo "Voici l'élément 0 : ${ARRAY[0]}"
Ajout/modification d'un élément

Code : Tout sélectionner

ARRAY[9]=f
ARRAY=("${ARRAY[@]}" ff )
Longueur d'un élément

Code : Tout sélectionner

echo "Voici la longueur de l'élément 3 : ${#ARRAY[3]}"
Extraction par offset et longueur

Code : Tout sélectionner

echo "Donne-moi les 2 éléments à partir de l'élément 4 : ${ARRAY[@]:4:2}"
Extraction par offset et longueur, pour un élément particulier

Code : Tout sélectionner

echo ${ARRAY[8]:1:3}
Chercher et remplacer dans un tableau sans modifier le tableau

Code : Tout sélectionner

echo ${ARRAY[@]/abcd/xyz}
Supprimer un élément (élément vide)

Code : Tout sélectionner

unset ARRAY[8]
Suppression : tableau de 0 avec 4 éléments concaténé avec le tableau de la pos 5 à la fin

Code : Tout sélectionner

pos=4
ARRAY=(${ARRAY[@]:0:$pos} ${ARRAY[@]:$(($pos + 1))})
Vider un tableau entier

Code : Tout sélectionner

unset ARRAY
Concaténer 2 tableaux

Code : Tout sélectionner

Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');
Shell=('bash' 'csh' 'jsh' 'rsh' 'ksh' 'rc' 'tcsh');
UnixShell=("${Unix[@]}" "${Shell[@]}")
echo ${UnixShell[@]}
echo ${#UnixShell[@]}
Script commenté

Code : Tout sélectionner

#!/bin/bash

## Création des tableaux ##
BASE=( `pacman -Qqg base` )
BASEDEV=( `pacman -Qqg base-devel` )
XFCE=( `pacman -Qqg xfce4` )
XFCEG=( `pacman -Qqg xfce4-goodies` )
AUR=( `pacman -Qqm` )
TOT=( `pacman -Qqe` )
TOTNB=${#TOT[@]}
Pacman est le gestionnaire de paquet d'Archlinux.
option Q : on interroge la base de paquets installés
option g : on demande les paquets appartenant au groupe (base, base-devel...)
option q : on affiche uniquement le nom des paquet (pas de groupe d'appartenance, pas de version de paquet)
option m : lister les paquets étrangés, c'est à dire n’appartenant pas à un dépôt (compilé avec une recette)
option e : affiche les paquets explicitement installé, on ne liste pas les dépendances

Code : Tout sélectionner

## Nettoyage de TOT ##
nettoie()
{
	PARAMTAB="$1"
	TAB=( $(eval echo \${${PARAMTAB}[@]}) )
Passer un tableau en paramètre ne se fais pas avec un simple $1! Je ne sais pas si c'est la manière la plus orthodoxe de faire mais elle fonctionne.

Code : Tout sélectionner

	m=0
	while [ $m -lt $TOTNB ]
	do
		n=0
		while [ $n -lt ${#TAB[@]} ]
		do
			# sortir de la boucle si la valeur de TOT est nulle
			# valable pour les passes > 1
			if [ -z ${TOT[$m]} ]
			then
				break
			fi
			if [ ${TOT[$m]} == ${TAB[$n]} ]
			then
				unset TOT[$m]
				# sortir de la boucle si la valeur de TOT a été mise à zéro
				break
			fi
			n=$[$n+1]
		done
		m=$[$m+1]
	done
}

nettoie BASE
nettoie BASEDEV
nettoie XFCE
nettoie XFCEG
nettoie AUR
Noter le $TOTNB utiliser dans les boucles while et pas le ${#TOT[@]}.
Tout au début de mon script je compte les éléments de mon tableau. En effet ${#TOT[@]} compte les éléments non-nuls du tableau !
Or je n'arrête d'en créer des éléments nuls ! Je ne fais même que ça.

Code : Tout sélectionner

## Génération du journal ##
OUTPUT=~/Developpement/archpkg_`date +%y%m%d`.txt
rm -f ~/Developpement/archpkg_*
Définition du fichier journal et suppression des anciens fichiers.

Code : Tout sélectionner

echo -e "--------------------" > $OUTPUT
echo -e "+ Installed Groups +" >> $OUTPUT
echo -e "--------------------\n" >> $OUTPUT
echo -e "base          : ${#BASE[@]}/$(pacman -Sqg base | wc -l) paquets" >> $OUTPUT
echo -e "base-devel    : ${#BASEDEV[@]}/$(pacman -Sqg base-devel | wc -l) paquets" >> $OUTPUT
echo -e "xfce4         : ${#XFCE[@]}/$(pacman -Sqg xfce4 | wc -l) paquets" >> $OUTPUT
echo -e "xfce4-goodies : ${#XFCEG[@]}/$(pacman -Sqg xfce4-goodies | wc -l) paquets\n" >> $OUTPUT
option S : permet d'interroger la base de paquets distante

Code : Tout sélectionner

echo -e "---------------------------------" >> $OUTPUT
echo -e "+ Explicitly installed Packages +" >> $OUTPUT
echo -e "---------------------------------\n" >> $OUTPUT

echo -e "${#TOT[@]} paquets\n" >> $OUTPUT

i=0
while [ $i -lt $TOTNB ]
do
	if [ -n "${TOT[$i]}" ]
	then
		echo -e "${TOT[$i]}" >> $OUTPUT
	fi
	i=$[$i+1]
done
J'affiche les éléments non-nuls du tableau un à un. Je n'ai pas envie d'avoir des trous dans ma liste et surtout je veux un nom de paquet par ligne ! pas une ligne unique longue comme 10 bras !

Code : Tout sélectionner

echo -e "\n----------------" >> $OUTPUT
echo      "+ AUR Packages +" >> $OUTPUT
echo -e   "----------------\n" >> $OUTPUT

echo -e   "${#AUR[@]} paquets\n" >> $OUTPUT
pacman -Qqm >> $OUTPUT
Conclusion
Franchement, manipuler des tableaux avec bash est faisable mais la syntaxe est vraiment difficile à retenir ! :(
J’espère que c'est plus simple dans d'autres langages ! :oops:
Répondre