#1 Le 16/08/2008, à 23:42
- fnx
[Resolu] lire un fichier ligne par ligne en bash
Bonjour,
Je partage une petite astuce pour effectuer cette opération apparemment simple, mais qui m'a causée bien du souci:
Objectif: lire ligne par ligne les données d'un fichier de données data.txt
Voici la solution la plus élégante que j'ai trouvé, mais il y en a surement d'autres:
fichier="data.txt"
oldIFS=$IFS # sauvegarde du séparateur de champ
IFS=$'\n' # nouveau séparateur de champ, le caractère fin de ligne
for ligne in $(<$fichier)
do
echo $ligne
done
Pour info IFS= Input Field Separator (Séparateur de champs en entrée).
c'est le code du caractère qui est utilisé par bash pour fractionner les paramètres passés en entrée.
Par défaut il vaut $'\ ' (cad le caractère espace).
Dans le code précédent, je le modifie pour prendre la valeur $'\n' (cad saut de ligne),
NB: $'\t' correspond à une tabulation.
NB2: bien mettre des ' et non "
NB3: dans la boucle for in $(<$fichier) est équivalent à in $(cat $fichier)
Dernière modification par fnx (Le 17/08/2008, à 01:15)
Hors ligne
#2 Le 17/08/2008, à 01:13
- fnx
Re : [Resolu] lire un fichier ligne par ligne en bash
Encore une astuce, si dans la ligne vous ne souhaitez que garder les caractères avant un motif (par exemple ":" )
modifier la ligne :
echo $ligne
par
echo ${ligne%%:*}
Pour plus de détails voir les caractères de substitution dans bash:
#, ##, % et %% , cf. http://abs.traduc.org/abs-5.0-fr/ch09s03.html#pctpatref
Dernière modification par fnx (Le 17/08/2008, à 01:17)
Hors ligne
#3 Le 17/08/2008, à 16:56
- Link31
Re : [Resolu] lire un fichier ligne par ligne en bash
while read line; do echo $line; done < fichier
Hors ligne
#4 Le 12/03/2010, à 19:42
- Nfjord
Re : [Resolu] lire un fichier ligne par ligne en bash
while read line; do echo $line; done < fichier
Bonjour,
j'ai justement un problème avec ce code : il ne m'affiche pas la dernière ligne de mon fichier ! Je n'arrive pas à comprendre pourquoi...
It's always a long day, 86,400 won't fit into a short.
Hors ligne
#5 Le 12/03/2010, à 19:44
- kyncani
Re : [Resolu] lire un fichier ligne par ligne en bash
C'est bien la première fois que j'entend que "while read line" ne fonctionne pas
Hors ligne
#6 Le 12/03/2010, à 19:53
- Nfjord
Re : [Resolu] lire un fichier ligne par ligne en bash
Bon et bien c'est à n'y rien comprendre. J'ai supprimé une ligne dans le fichier que je veux lire, j'ai exécuté le script et ça a fonctionné. J'ai remis la ligne que j'avais supprimé et j'ai re-exécuté et ça marche... tant mieux...
It's always a long day, 86,400 won't fit into a short.
Hors ligne
#7 Le 12/03/2010, à 20:29
- tukuyomi
Re : [Resolu] lire un fichier ligne par ligne en bash
EDIT: ce post est TOTALEMENT FAUX ¬¬ je viens d'essayer, et en fait, ça marche même sans ligne vide.
Pourtant, je jurerai avoir eu ce problème par le passé...
-----
Bon et bien c'est à n'y rien comprendre. J'ai supprimé une ligne dans le fichier que je veux lire, j'ai exécuté le script et ça a fonctionné. J'ai remis la ligne que j'avais supprimé et j'ai re-exécuté et ça marche... tant mieux...
Il faut ajouter une ligne vierge à la fin de ton fichier.
Admettons le fichier suivant:
1 ligne1
2 ligne2
3 ligne3
4 ligne4
5 ligne5
6
while read line.... done < fichier lira les lignes de 1 à 5. Si tu retires la ligne 6, il ne lira que les lignes de 1 à 4
Dernière modification par tukuyomi (Le 12/03/2010, à 20:32)
Hors ligne
#8 Le 12/03/2010, à 20:37
- kyncani
Re : [Resolu] lire un fichier ligne par ligne en bash
Apparemment, while read i passe la dernière ligne si elle ne finit pas par un \n
Hors ligne
#9 Le 12/03/2010, à 22:14
- Link31
Re : [Resolu] lire un fichier ligne par ligne en bash
En effet, c'est un problème de retour à la ligne à la fin du fichier.
Pour ceux qui auraient testé et qui auraient des résultats contradictoires, il faut savoir que certaines éditeurs ajoutent automatiquement un retour à la ligne à la fin du fichier (pour éviter ce genre de désagrément... ).
Hors ligne
#10 Le 12/03/2010, à 23:14
- gilbert
Re : [Resolu] lire un fichier ligne par ligne en bash
et mapfile ne permet pas d'éviter ce problème de la dernière ligne ???
mapfile -t monArray < fichier
for i in ${monArray}; do
echo $i;
done
Dernière modification par gilbert (Le 12/03/2010, à 23:16)
Simplement moi-même..
Hors ligne
#11 Le 13/03/2010, à 08:14
- Nfjord
Re : [Resolu] lire un fichier ligne par ligne en bash
Ce qui est bizarre, c'est que en fait, j'ai plusieurs fichiers log qui proviennent d'une simulation. Comme je ne souhaite pas traiter tous ces fichiers, je commence par rechercher parmi tous les fichiers ce dont la dernière ligne contient la chaîne "no more energy". Pour cela, je fais un
grep "no more energy" *
et je récupère la liste des fichiers log qui m'intéressent. J'execute ensuite la boucle while read file sur ces fichiers et il ne m'affiche donc pas cette dernière ligne (qui contient le "no more energy" alors qu'il l'a bien trouvée avec le grep).
J'ai remarqué finalement que je dois ouvrir le fichier (avec gvim ou autre) et le sauvegarder (je tape juste la commande :wq). A ce moment-là, la boucle while read line m'affiche cette dernière ligne. Cela signifie que, lors de la simulation, peut-être qu'il manque un caractère End-of-File ou qqc du genre que la commande :wq ajouterai ? Tout cela me semble assez farfelu... Y'a-t-il une commande qui permette d'afficher toutes les "commandes" (\n, \t, eof, ...) présentes dans un fichier ?
@ gilbert : ta commande ne m'affiche que la première ligne du fichier.
Dernière modification par Nfjord (Le 13/03/2010, à 08:19)
It's always a long day, 86,400 won't fit into a short.
Hors ligne
#12 Le 13/03/2010, à 08:19
- tukuyomi
Re : [Resolu] lire un fichier ligne par ligne en bash
$ od -c fichier
Hors ligne
#13 Le 13/03/2010, à 08:24
- Nfjord
Re : [Resolu] lire un fichier ligne par ligne en bash
Ah super, merci tukuyoml ! Lorsque j'execute od -c sur mon fichier, la dernière ligne se termine par le caractère 'y' de "no more energy". Lorsque je l'ouvre avec gvim puis je sauvegarde et quitte, od -c me dit que le dernier caractère est maintenant '\n'. Cela confirme ce qu'a dit kyncani.
Le fait qu'il manque un '\n' en fin de fichier peut-il provenir d'une mauvaise fermeture du fichier lors de la simulation ? Pourtant, dans mon programme de simulation (en C), j'ouvre le fichier avec fopen(), j'écris dedans et à la fin de la simu je le ferme correctement avec fclose().
Merci en tout cas pour votre aide.
It's always a long day, 86,400 won't fit into a short.
Hors ligne
#14 Le 13/03/2010, à 08:27
- credenhill
Re : [Resolu] lire un fichier ligne par ligne en bash
. Y'a-t-il une commande qui permette d'afficher toutes les "commandes" (\n, \t, eof, ...) présentes dans un fichier ?
cat -A fichier
awk '{print}' fichier
imprime bien la dernière ligne même si elle ne termine pas par \n
Dernière modification par credenhill (Le 13/03/2010, à 08:34)
Hors ligne
#15 Le 13/03/2010, à 09:45
- kyncani
Re : [Resolu] lire un fichier ligne par ligne en bash
Le fait qu'il manque un '\n' en fin de fichier peut-il provenir d'une mauvaise fermeture du fichier lors de la simulation ?
Tu as peut-être mis un truc du genre fprintf(logfile,"no more energy") au lieu de fprintf(logfile,"no more energy\n") ?
Hors ligne
#16 Le 13/03/2010, à 12:03
- Totor
Re : [Resolu] lire un fichier ligne par ligne en bash
Bonjour,
Attention, la version while read line; do echo $line; done < fichier est erronée en l'état.
En effet, sans modification de l'IFS, les blancs en début/fin de ligne seront supprimés.
Pour contourner ce problème, deux solutions :
while read
do
echo "${REPLY}"
done < fichier
# ou
while IFS=$'\n' read ligne
do
echo "${ligne}"
done < fichier
Note : pour vous en convaincre, lors de l'affichage, encadrez le résultat par des caractères.
-- Lucid Lynx --
Hors ligne
#17 Le 13/03/2010, à 12:41
- Nfjord
Re : [Resolu] lire un fichier ligne par ligne en bash
Tu as peut-être mis un truc du genre fprintf(logfile,"no more energy") au lieu de fprintf(logfile,"no more energy\n") ?
Exact !!! Quelle bête erreur. Merci, maintenant je pense que ça va fonctionner avec le while read line.
It's always a long day, 86,400 won't fit into a short.
Hors ligne
#18 Le 13/03/2010, à 13:48
- kyncani
Re : [Resolu] lire un fichier ligne par ligne en bash
Hors ligne
#19 Le 28/11/2013, à 21:51
- capitainabloc
Re : [Resolu] lire un fichier ligne par ligne en bash
Bonjour à tous,
en restant dans le même esprit, comment lire/afficher uniquement le 5eme caractere de chaque ligne?
Dernière modification par capitainabloc (Le 28/11/2013, à 21:53)
Hors ligne
#20 Le 28/11/2013, à 22:18
- fnx
Re : [Resolu] lire un fichier ligne par ligne en bash
Essaie avec
cut -c 5 $ligne
au lieu de
echo $ligne
Hors ligne
#21 Le 28/11/2013, à 22:22
- pingouinux
Re : [Resolu] lire un fichier ligne par ligne en bash
Bonsoir,
cut -c 5 fichier
Hors ligne
#22 Le 28/11/2013, à 22:40
- capitainabloc
Re : [Resolu] lire un fichier ligne par ligne en bash
merci beaucoup, mais voila:
j'ai un fichier, apres quelques modif qui est ainsi:
99802187971376187106302119011332813
99902186911375520106402117951332146
100002185851374854106502116891331479
100102184791374187106602115821330806
100202183731373520106702114761330140
100302182671372854106802113701329473
...
je souhaite vérifier si le caractère N°5 = 0, et dans ce cas la insérer un point apres le 2eme caractere.
c'est sur la vérification que je bloque.
je pars sur qque chose de ce genre:
#!/bin/sh
do
if [ caractere 5 = "0" ]
then
sed 's/^.\{2\}/&./'
return 1
else
sed 's/^.\{1\}/&./'
fi
done < yo.txt
c'est sur la condition que je bloque, et le cut ne m'aidera pas du coup.
Hors ligne
#23 Le 28/11/2013, à 23:45
- pingouinux
Re : [Resolu] lire un fichier ligne par ligne en bash
Est-ce ceci que tu veux ?
while read ligne; do [ "$(cut -c5 <<<"$ligne")" = 0 ] && sed 's/^../&./' <<<"$ligne" || sed 's/^./&./' <<<"$ligne"; done <yo.txt
Ce qui donne :
9.9802187971376187106302119011332813
9.9902186911375520106402117951332146
10.0002185851374854106502116891331479
10.0102184791374187106602115821330806
10.0202183731373520106702114761330140
10.0302182671372854106802113701329473
Ajouté :
Ou bien :
while read ligne; do [ "$(cut -c5 <<<"$ligne")" = 0 ] && n=2 || n=1; sed "s/^.\{$n\}/&./" <<<"$ligne"; done <yo.txt
Dernière modification par pingouinux (Le 29/11/2013, à 07:31)
Hors ligne
#24 Le 29/11/2013, à 08:36
- capitainabloc
Re : [Resolu] lire un fichier ligne par ligne en bash
Whao, super!
j'avais les cartes en main, mais impossible de tout mettre dans le bon ordre.
je suis novice, et ilfaut que ca entre!
merci beaucoup pour ton aide en tout cas.
Hors ligne
#25 Le 29/11/2013, à 08:52
- pingouinux
Re : [Resolu] lire un fichier ligne par ligne en bash
Attention, en #23, ce sont des commandes bash, et non sh.
Hors ligne