Préambule
Une des erreurs les plus communes dans l’apprentissage des scripts « bash » sous GNU/LInux pour lire un fichier ligne par ligne, est d’utiliser une boucle « for » (for line in $(cat file.txt); do …), ce qui dans cet exemple conduit à une évaluation, non pas de chaque ligne du fichier, mais de chaque mot ! Ce qui n’est pas du tout le but recherché…
Exemple de sortie avec une boucle « for » :
for line in $(cat file.txt); do echo "$line" ; done Ceci est la ligne n° 1 Ceci est la ligne n° 2 Ceci [...]
La solution consiste à utiliser une boucle « while » couplée à la commande interne « read ».
Mais il est cependant possible d’obtenir le me résultat avec une boucle « for » à condition de changer la valeur de la variable « $IFS » (Internal Field Separator, séparateur de champ interne) avant de lancer la boucle. C’est ce que nous verrons par la suite…
Boucle while
La boucle « while » reste la méthode la plus appropriée et la plus simple pour lire un fichier ligne par ligne.
Syntaxe
while read ligne do commande done < fichier
Exemple
Le fichier de départ :
Ceci est la ligne n° 1 Ceci est la ligne n° 2 Ceci est la ligne n° 3 Ceci est la ligne n° 4 Ceci est la ligne n° 5
Les instructions en ligne de commande :
while read line; do echo -e "$line\n"; done < file.txt
ou dans un script « bash » :
#! /bin/bash while read line do echo -e "$line\n" done < file.txt
La sortie sur l’écran (stdout) :
Ceci est la ligne n° 1 Ceci est la ligne n° 2 Ceci est la ligne n° 3 Ceci est la ligne n° 4 Ceci est la ligne n° 5
Astuces
Il vous est tout a fait possible à partir d’un fichier structuré (comme un carnet d’adresse ou /etc/passwd par exemple), de récupérer les valeurs de chaque champ et de les affecter à plusieurs variables avec la commande « read ». Attention toutefois de bien assigner à la variable « IFS » le bon séparateur de champ (espace par défaut).
Exemple :
#! /bin/bash while IFS=: read user pass uid gid full home shell do echo -e "$full :\n\ Pseudo : $user\n\ UID :\t $uid\n\ GID :\t $gid\n\ Home :\t $home\n\ Shell :\t $shell\n\n" done < /etc/passwd
Bonus
while read i; do echo -e « Paramètre : $i »; done < <(echo -e « a\nab\nc »)
Boucle for
Si la boucle « while » reste la méthode la plus simple, elle a toutefois un inconvénient majeur, à savoir qu’elle annihile le formatage des lignes et notamment les espaces et tabulations ;-\
Heureusement la boucle « for » couplée avec un changement d’IFS permet de garder la structure du document en sortie.
Syntaxe
oldIFS=$IFS # sauvegarde du séparateur de champ IFS=$’\n’ # nouveau séparateur de champ, le caractère fin de ligne for ligne in $(cat fichier) do commande done IFS=$old_IFS # rétablissement du séparateur de champ par défaut