Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 17/08/2008, à 00: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, à 02:15)

Hors ligne

#2 Le 17/08/2008, à 02: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, à 02:17)

Hors ligne

#3 Le 17/08/2008, à 17: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, à 20:42

Nfjord

Re : [Resolu] lire un fichier ligne par ligne en bash

Link31 a écrit :
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, à 20: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 roll

Hors ligne

#6 Le 12/03/2010, à 20: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, à 21: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é...
-----

Nfjord a écrit :

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, à 21:32)

Hors ligne

#8 Le 12/03/2010, à 21: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, à 23: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... smile).

Hors ligne

#10 Le 13/03/2010, à 00: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 13/03/2010, à 00:16)


Simplement moi-même..

Hors ligne

#11 Le 13/03/2010, à 09: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, à 09:19)


It's always a long day, 86,400 won't fit into a short.

Hors ligne

#12 Le 13/03/2010, à 09:19

tukuyomi

Re : [Resolu] lire un fichier ligne par ligne en bash

$ od -c fichier

Hors ligne

#13 Le 13/03/2010, à 09: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, à 09:27

credenhill

Re : [Resolu] lire un fichier ligne par ligne en bash

Nfjord a écrit :

. 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, à 09:34)

Hors ligne

#15 Le 13/03/2010, à 10:45

kyncani

Re : [Resolu] lire un fichier ligne par ligne en bash

Nfjord a écrit :

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, à 13: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, à 13:41

Nfjord

Re : [Resolu] lire un fichier ligne par ligne en bash

kyncani a écrit :

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. smile


It's always a long day, 86,400 won't fit into a short.

Hors ligne

#18 Le 13/03/2010, à 14:48

kyncani

Re : [Resolu] lire un fichier ligne par ligne en bash

smile

Hors ligne

#19 Le 28/11/2013, à 22: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, à 22:53)

Hors ligne

#20 Le 28/11/2013, à 23: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, à 23:22

pingouinux

Re : [Resolu] lire un fichier ligne par ligne en bash

Bonsoir,

cut -c 5 fichier

Hors ligne

#22 Le 28/11/2013, à 23: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.

hmm

Hors ligne

#23 Le 29/11/2013, à 00: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, à 08:31)

Hors ligne

#24 Le 29/11/2013, à 09: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, à 09: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