Comment analyser un fichier CSV en Bash ? `
J'interviens tardivement sur cette question et en tant que bash offrent de nouvelles fonctionnalités, parce que cette question porte sur bash et parce qu'aucune des réponses déjà postées ne montre cette façon puissante et conforme de faire précisément ceci .
Parsing des fichiers CSV sous bash
en utilisant module chargeable
Conforme à RFC 4180 une chaîne comme cet échantillon Ligne CSV :
12,22.45,"Hello, ""man"".","A, b.",42
devrait être divisé en
1 12
2 22.45
3 Hello, "man".
4 A, b.
5 42
bash chargeable Modules compilés en .C.
Sous bash vous avez pu créer, modifier et utiliser chargeable c modules compilés . Une fois chargés, ils fonctionnent comme n'importe quel autre intégré ! ! ( Vous pouvez trouver plus d'informations sur arbre source . ;)
L'arbre des sources actuel (15 octobre 2021, bash V5.1-rc3) contient un tas d'échantillons :
accept listen for and accept a remote network connection on a given port
asort Sort arrays in-place
basename Return non-directory portion of pathname.
cat cat(1) replacement with no options - the way cat was intended.
csv process one line of csv data and populate an indexed array.
dirname Return directory portion of pathname.
fdflags Change the flag associated with one of bash's open file descriptors.
finfo Print file info.
head Copy first part of files.
hello Obligatory "Hello World" / sample loadable.
...
tee Duplicate standard input.
template Example template for loadable builtin.
truefalse True and false builtins.
tty Return terminal name.
uname Print system information.
unlink Remove a directory entry.
whoami Print out username of current user.
Il y a un travail complet cvs
prêt à être utilisé dans examples/loadables
répertoire : csv.c ! !
Sous Debian GNU/Linux vous devrez peut-être installer bash-builtins paquet par
apt install bash-builtins
Utilisation de bash-builtins chargeables :
Ensuite :
enable -f /usr/lib/bash/csv csv
A partir de là, vous pouvez utiliser cvs
en tant que bash builtin .
Avec mon échantillon : 12,22.45,"Hello, ""man"".","A, b.",42
csv -a myArray '12,22.45,"Hello, ""man"".","A, b.",42'
printf "%s\n" "${myArray[@]}" | cat -n
1 12
2 22.45
3 Hello, "man".
4 A, b.
5 42
Puis dans une boucle, traitement d'un fichier.
while IFS= read -r line;do
csv -a aVar "$line"
printf "First two columns are: [ '%s' - '%s' ]\n" "${aVar[0]}" "${aVar[1]}"
done <myfile.csv
Cette façon de faire est clairement la plus rapide et la plus solide que toute autre combinaison de bash builtins ou fork à tout binaire.
Malheureusement, selon l'implémentation de votre système, si votre version de bash a été compilé sans loadable
cela peut ne pas fonctionner...
Exemple complet avec des champs CSV multilignes.
Voici un petit exemple de fichier avec 1 titre, 4 colonnes et 3 rangs. Parce que deux champs contiennent nouvelle ligne les fichiers sont 6 longueur des lignes.
Id,Name,Desc,Value
1234,Cpt1023,"Energy counter",34213
2343,Sns2123,"Temperatur sensor
to trigg for alarm",48.4
42,Eye1412,"Solar sensor ""Day /
Night""",12199.21
Et un petit script capable d'analyser ce fichier correctement :
#!/bin/bash
enable -f /usr/lib/bash/csv csv
file="sample.csv"
exec {FD}<"$file"
read -ru $FD line
csv -a headline "$line"
printf -v fieldfmt '%-8s: "%%q"\\n' "${headline[@]}"
while read -ru $FD line;do
while csv -a row "$line" ; ((${#row[@]}<${#headline[@]})) ;do
read -ru $FD sline || break
line+=$'\n'"$sline"
done
printf "$fieldfmt\\n" "${row[@]}"
done
Voici mon rendu : (j'ai utilisé printf "%q"
pour représenter des caractères non imprimables comme nouvelles lignes comme $'\n'
)
Id : "1234"
Name : "Cpt1023"
Desc : "Energy\ counter"
Value : "34213"
Id : "2343"
Name : "Sns2123"
Desc : "$'Temperatur sensor\nto trigg for alarm'"
Value : "48.4"
Id : "42"
Name : "Eye1412"
Desc : "$'Solar sensor "Day /\nNight"'"
Value : "12199.21"
Vous pourriez y trouver un échantillon de travail complet : csvsample.sh.txt ou csvsample.sh .
Attention :
Bien sûr, l'analyse des CSV en utilisant cette méthode n'est pas parfaite ! Cela fonctionne pour de nombreux fichiers CSV simples, mais attention à l'encodage et à la sécurité ! Par exemple, ce module ne sera pas capable de gérer les champs binaires !
Lire attentivement Commentaires sur le code source csv.c y RFC 4180 !
7 votes
Avez-vous envisagé d'utiliser
awk
pour utiliser$1
,$2
, etc?4 votes
En tant que note de côté: commande < <(echo "string") ---> commande <<< "string"
1 votes
Le programme en ligne de commande 'cut' a été conçu à cet effet : ss64.com/bash/cut.html
0 votes
Possible duplicate de stackoverflow.com/questions/36287982/…
0 votes
Vous voulez vous débarrasser de l'utilisation inutile de
cat