3 votes

Analyse d'un fichier .csv dans bash, ne lit pas la dernière ligne

J'essaie d'analyser un fichier csv que j'ai créé avec Google Spreadsheet. Il est très simple pour des raisons de test, et se résume à.. :

1,2
3,4
5,6

Le problème est que le fichier csv ne se termine pas par un caractère de retour à la ligne. cat le fichier dans BASH, j'obtiens

MacBook-Pro:Desktop kkSlider$ cat test.csv 
1,2 
3,4 
5,6MacBook-Pro:Desktop kkSlider$ 

Je veux juste lire ligne par ligne dans un script BASH en utilisant une boucle while comme tous les guides le suggèrent, et mon script ressemble à ceci :

while IFS=',' read -r last first
do
    echo "$last $first"
done < test.csv

Le résultat est le suivant :

MacBook-Pro:Desktop kkSlider$ ./test.sh
1 2
3 4

Une idée sur la manière dont je pourrais faire en sorte qu'il lise cette dernière ligne et la répercute ?

Merci d'avance.

7voto

paxdiablo Points 341644

Vous pouvez force l'entrée de votre boucle doit se terminer par un retour à la ligne :

#!/bin/bash
(cat test.csv ; echo) | while IFS=',' read -r last first
do
    echo "$last $first"
done

Malheureusement, cela peut entraîner l'apparition d'une ligne vide à la fin de la sortie si l'entrée comporte déjà une nouvelle ligne à la fin. Vous pouvez corriger cela avec un petit ajout :

!/bin/bash
(cat test.csv ; echo) | while IFS=',' read -r last first
do
    if [[ $last != "" ]] ; then
        echo "$last $first"
    fi
done

Une autre méthode s'appuie sur le fait que les valeurs sont en train d'être placé dans les variables par l'intermédiaire du read mais ils ne sont tout simplement pas produits en raison de la while déclaration :

#!/bin/bash
while IFS=',' read -r last first
do
    echo "$last $first"
done <test.csv
if [[ $last != "" ]] ; then
    echo "$last $first"
fi

Celle-ci fonctionne sans qu'il soit nécessaire de créer un autre sous-shell pour modifier l'entrée de la fonction while déclaration.


Bien sûr, je suppose ici que vous voulez faire plus à l'intérieur de la boucle que de simplement sortir les valeurs avec un espace au lieu d'une virgule. Si c'est tout ce que vous voulez faire, il existe d'autres outils mieux adaptés qu'un bash de la boucle de lecture, comme par exemple :

tr "," " " <test.csv

2voto

cat file |sed -e '${/^$/!s/$/\n/;}'| while IFS=',' read -r last first; do echo "$last $first"; done

1voto

Gordon Davisson Points 22534

Si la dernière ligne (non terminée) doit être traitée différemment du reste, la version de @paxdiablo avec l'élément supplémentaire if est la meilleure solution ; mais si elle doit être traitée comme toutes les autres, il est plus propre de la traiter dans la boucle principale.

Vous pouvez intégrer la condition "si la dernière ligne n'est pas terminée" dans la condition de la boucle principale comme suit :

while IFS=',' read -r last first || [ -n "$last" ]
do
    echo "$last $first"
done < test.csv

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X