HOWTO · Linux
Comment lire un fichier ligne par ligne en utilisant Bash
Nous utilisons la commande read dans Bash pour lire un fichier ligne par ligne.
Sur cette page
Avec la commande read dans une boucle while, Bash peut traiter un fichier texte une ligne à la fois. Cette méthode lit les données au fil de l’eau : le script n’a donc pas besoin de garder tout le fichier en mémoire. Utilisez IFS= pour conserver les espaces au début et à la fin des lignes, -r pour préserver les barres obliques inverses, et mettez "$line" entre guillemets chaque fois que vous développez cette variable.
Lire un fichier ligne par ligne avec une boucle while
Une boucle fiable lit le fichier au moyen d’une redirection d’entrée. La condition || [[ -n $line ]] permet aussi de traiter la dernière ligne si le fichier ne se termine pas par un saut de ligne. La boucle parcourt le fichier au fil de l’eau et conserve le total en cours dans le shell actuel.
L’exemple complet ci-dessous crée son propre fichier de nombres, affiche chaque valeur et additionne les six nombres : 1, 5, 6, 7, 8 et 10. Leur somme est 37. Les libellés et les messages affichés dans les exemples restent en anglais, car les blocs de code et de sortie sont conservés à l’identique.
#!/usr/bin/env bash
set -u
file=$(mktemp)
trap 'rm -f "$file"' EXIT
printf '%s\n' 1 5 6 7 8 10 > "$file"
sum=0
printf 'The numbers in the file are:\n'
while IFS= read -r line || [[ -n $line ]]; do
printf '%s\n' "$line"
sum=$((sum + line))
done < "$file"
printf 'The sum of the numbers in the file is:%s\n' "$sum"
The numbers in the file are:
1
5
6
7
8
10
The sum of the numbers in the file is:37
La redirection d’entrée maintient la boucle dans le shell actuel. Les modifications, comme le total en cours, restent donc disponibles après la boucle. Évitez un développement sans guillemets tel que $line : le découpage en mots et le développement des noms de fichiers peuvent en modifier le contenu.
Découper chaque ligne en champs
Pour séparer des enregistrements à l’aide d’un délimiteur, lisez d’abord chaque ligne brute, puis affectez ses champs. Avec une lecture utilisant un délimiteur, la dernière variable de read reçoit les champs restants. Cet exemple crée et traite les cinq enregistrements : Rohit-10, Harish-30, Manish-50, Kapil-10 et Anish-20. La condition de fin de ligne traite également un dernier enregistrement non vide si le fichier ne se termine pas par un saut de ligne.
#!/usr/bin/env bash
set -u
file=$(mktemp)
trap 'rm -f "$file"' EXIT
printf '%s\n' 'Rohit-10' 'Harish-30' 'Manish-50' 'Kapil-10' 'Anish-20' > "$file"
while IFS= read -r line || [[ -n $line ]]; do
IFS=- read -r name earnings <<< "$line"
printf '%s has made earnings of %s pounds today!\n' "$name" "$earnings"
done < "$file"
Rohit has made earnings of 10 pounds today!
Harish has made earnings of 30 pounds today!
Manish has made earnings of 50 pounds today!
Kapil has made earnings of 10 pounds today!
Anish has made earnings of 20 pounds today!
Ici, IFS=- définit le trait d’union comme délimiteur pour la lecture avec affectation des champs. Avec deux variables, name reçoit le texte précédant le premier trait d’union et earnings reçoit le reste. À l’affichage, gardez les variables entre guillemets afin que leur contenu soit transmis comme une valeur unique.
Choisir une autre méthode de lecture de fichier en Bash
Utilisez le modèle while IFS= read -r line pour traiter chaque ligne dès sa lecture ou lorsque le fichier risque d’être plus volumineux que la mémoire disponible. Pour un fichier ordinaire, redirigez-le directement vers la boucle : exécuter cat avec une substitution de processus n’apporte rien dans ce cas. La substitution de processus peut être utile si la boucle doit lire la sortie générée par une commande plutôt qu’un fichier.
Si votre installation de Bash fournit mapfile, cette commande peut charger les lignes d’un fichier dans un tableau, par exemple avec mapfile -t lines < "$file". Choisissez cette méthode si les étapes suivantes ont besoin d’accéder aux lignes par index ou de les parcourir plusieurs fois, et si le fichier tient en mémoire. L’option -t retire le saut de ligne final de chaque ligne. La disponibilité dépend de l’installation de Bash ; utilisez donc la boucle de lecture au fil de l’eau si vous avez besoin d’une méthode plus largement applicable.