#1 Le 09/05/2025, à 21:57
- Zococo
[Résolu]Tableau associatif et boucles - perte du tableau fin boucle
Bonjour,
je lis un fichier texte à l'intérieur d'un script. C'est assez simple et je maîtrise bien l'exercice. Je renseigne donc deux tableaux associatifs nommés tableau_occurrences_deuxieme_info et tableau_occurrences_troisieme_info. A la fin de la boucle, j'obtiens dans chacun des tableaux le nombre d’occurrences des valeurs passées en colonnes 2 et 3, les valeurs correspondant ainsi aux clés du tableau.
Voici un script parfaitement fonctionnel :
#!/bin/bash
# Initialisation
declare -A tableau_occurrences_deuxieme_info
declare -A tableau_occurrences_troisieme_info
# Lecture des informations du fichier
while IFS=$'\t' read -r premiere_info deuxieme_info troisieme_info; do
((tableau_occurrences_deuxieme_info[${deuxieme_info}]++))
((tableau_occurrences_troisieme_info[${troisieme_info}]++))
done < "${fichier_entree}"
# Affichage du résultat (je me limite à la colonne 2 pour ce poste déjà bien touffu mais je travaille aussi sur la 3)
echo "Occurrences uniques de la colonne 2 avec leur nombre d'apparitions :"
for occurrence in "${!tableau_occurrences_deuxieme_info[@]}";do
echo "$occurrence ${tableau_occurrences_deuxieme_info[$occurrence]}";
done
Par exemple, pour un fichier ainsi construit (séparateur tab) :
Paul Banane Bleu
Micheline Pomme Rouge
Arthur Poire Verte
Aline Banane Orange
André Poire Rose
Aurélie Banane Violette
Le résultat sera :
Occurrences uniques de la colonne 2 avec leur nombre d'apparitions :
Banane 3
Pomme 1
Poire 2
Jusqu'ici tout va bien. Mais j'ai un problème, mon fichier comporte une ligne d'en-tête que je ne souhaite pas traiter sinon les en-tête sont comptés comme des enregistrements. Le fichier est donc en fait celui-ci :
#Prénom Fruit Couleur
Paul Banane Bleu
Micheline Pomme Rouge
Arthur Poire Verte
Aline Banane Orange
André Poire Rose
Aurélie Banane Violette
J'obtiens le résultat suivant, qui ne me convient pas :
Occurrences uniques de la colonne 2 avec leur nombre d'apparitions :
Fruit 1
Banane 3
Pomme 1
Poire 2
Je suis donc allé explorer la toile et j'ai identifié deux solutions possibles. La première ne fonctionne pas. Elle consiste à placer un read -r _ < $fichier juste avant la boucle while :
read -r _ < "${fichier_entree}"
while IFS=$'\t' read -r premiere_info deuxieme_info troisieme_info; do
L'idée est que le premier read lit la 1ere ligne puis la boucle while les suivantes. Chez moi échec, la boucle reprend la lecture du fichier dès le début et donc j'ai toujours le même résultat.
L'autre solution consiste à confier la lecture du fichier à tail puis à rediriger le résultat vers while par un pipe ainsi construit :
tail -n +2 "${fichier_entree}" | while IFS=$'\t' read -r premiere_info deuxieme_info troisieme_info; do
Ce code évite de lire la première ligne, c'est bien. Malheureusement en sortie de boucle, le script perd le contenu des tableaux associatifs comme si ceux-ci étaient des variables locales à l'intérieur de la boucle. J'ai inséré des echo pour le débogage à l'intérieur du script et voici ce que j'obtiens.
Le code :
# Lecture des informations du fichier
tail -n +2 "${fichier_entree}" | while IFS=$'\t' read -r premiere_info deuxieme_info troisieme_info; do
((tableau_occurrences_deuxieme_info[${deuxieme_info}]++))
echo "Suivi : {deuxieme_info}] ${tableau_occurrences_deuxieme_info[${deuxieme_info}]}" # AFFICHAGE POUR LE DÉBOGAGE
done
# Verification en sortie de boucle
echo # saut de ligne
echo "Clés : ${!tableau_occurrences_deuxieme_info[@]}"
echo "Valeurs : ${tableau_occurrences_deuxieme_info[@]}"
Et le résultat :
Suivi : Banane 1
Suivi : Pomme 1
Suivi : Poire 1
Suivi : Banane 2
Suivi : Poire 2
Suivi : Banane 3
Clés :
Valeurs :
Et là j'avoue ne plus rien y comprendre, sauf à se dire qu'en sortie de boucle while, le contenu du tableau tableau_occurrences_deuxieme_info est réinitialisé.
Évidemment je peux m'en sortir en ajoutant un test sur le premier caractère de chaque ligne après la lecture, du style if [[ "${premiere_info:0:1}" != "#" ]] ; then mais cela signifie faire le test à chaque tour de la boucle. Compte tenu du faible volume de mes fichiers (100 à 200 lignes) ce n'est pas très grave mais ce n'est pas très "propre".
Est-ce que quelqu'un sur le forum pourrait m'expliquer ce qui se passe ? Et éventuellement me suggérer une solution de contournement ?
Par avance merci !
Dernière modification par Zococo (Hier à 00:20)
Ubuntu 24.04 (64 bits) - Gigabyte B250M-DS3H / Core i5-7600K (Kaby lake) - Microsoft surface Go 3
Hors ligne
#2 Le 09/05/2025, à 22:57
- Watael
Re : [Résolu]Tableau associatif et boucles - perte du tableau fin boucle
salut,
while IFS=$'\t' read -r premiere_info deuxieme_info troisieme_info; do
((tableau_occurrences_deuxieme_info[$deuxieme_info]++))
echo "Suivi : {deuxieme_info}] ${tableau_occurrences_deuxieme_info[$deuxieme_info]}" # AFFICHAGE POUR LE DÉBOGAGE
done < <(tail -n +2 "$fichier_entree" )
les accolades, sur les "variables plates", ici, ne servent à rien.
pourquoi tail | while read...Done ne permet pas d'obtenir les tableaux : parce qu'un pipeest exécuté dans un sous-shell. Or, hors d'un sous-shell, les variables qui y sont définies n'existent pas (comme dans un script par rapport au shell courant).
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#3 Le 09/05/2025, à 23:50
- Zococo
Re : [Résolu]Tableau associatif et boucles - perte du tableau fin boucle
Bonsoir et merci,
sinon ça ne faisait vraiment pas mon affaire tout ça mais c'est clair et en plus ça correspond à ce que je ressentais confusément.
Merci pour la solution, j'avais essayé un seul < en fin de boucle, mais 2 je n'y aurais pas pensé !
Bonne soirée,
Ubuntu 24.04 (64 bits) - Gigabyte B250M-DS3H / Core i5-7600K (Kaby lake) - Microsoft surface Go 3
Hors ligne
#4 Hier à 02:35
- Watael
Re : [Résolu]Tableau associatif et boucles - perte du tableau fin boucle
ce n'est pas deux <, c'est une redirection (<), et une substitution de processus (<(cmd...)).
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#5 Hier à 11:03
- Zococo
Re : [Résolu]Tableau associatif et boucles - perte du tableau fin boucle
Merci
Ubuntu 24.04 (64 bits) - Gigabyte B250M-DS3H / Core i5-7600K (Kaby lake) - Microsoft surface Go 3
Hors ligne