Je travaille sur un long script Bash. Je veux lire les cellules d'un fichier CSV dans les variables Bash. Je peux analyser les lignes et la première colonne, mais pas n'importe quelle autre colonne. Voici mon code jusqu'à présent:
cat myfile.csv|while read line
do
read -d, col1 col2 < <(echo $line)
echo "I got:$col1|$col2"
done
C'est seulement l'impression de la première colonne. En guise de test supplémentaire, j’ai essayé ce qui suit:
read -d, x y < <(echo a,b,)
Et $ y est vide. Alors j'ai essayé:
read x y < <(echo a b)
Et $ y est b
. Pourquoi?
Vous devez utiliser IFS
au lieu de -d
:
while IFS=, read -r col1 col2
do
echo "I got:$col1|$col2"
done < myfile.csv
Notez que pour l'analyse CSV à usage général, vous devez utiliser un outil spécialisé capable de gérer les champs entre guillemets avec des virgules internes, entre autres problèmes que Bash ne peut pas gérer seul. Des exemples de tels outils sont cvstool
et csvkit
.
De la page man
:
-d delim Le premier caractère de delim est utilisé pour terminer la ligne de saisie, plutôt que newline.
Vous utilisez -d,
qui terminera la ligne de saisie sur la virgule. Il ne lira pas le reste de la ligne. C'est pourquoi $ y est vide.
Nous pouvons analyser les fichiers CSV avec des chaînes citées et délimités par say | avec le code suivant
while read -r line
do
field1=$(echo $line | awk -F'|' '{printf "%s", $1}' | tr -d '"')
field2=$(echo $line | awk -F'|' '{printf "%s", $2}' | tr -d '"')
echo $field1 $field2
done < $csvFile
awk analyse les champs de chaîne en variables et tr supprime la citation.
Légèrement plus lent car awk est exécuté pour chaque champ.