J'ai un fichier csv qui ressemble à ceci:
1,'someval','otherval',,,,,
'','someotherval','some_otherval',,,,,
1BSD,'',,,,,
2,'val',,,,,
,,,,,,
2BSD,,,,,,
2BCD,,,,,,
Maintenant, je veux diviser le fichier chaque fois que la première colonne de la nouvelle ligne est un entier.
Donc, pour l’entrée csv ci-dessus <je dois obtenir 2 nouveaux fichiers avec le contenu:
1,'someval','otherval',,,,,
,'someotherval','some_otherval',,,,,
1BSD,'val',,,,,
et
2,'val',,,,,
,,,,,,
2BSD,,,,,,
2BCD,,,,,,
respectivement.
Comment puis-je accomplir cela en utilisant Bash et/ou Python? Merci.
Vous pouvez utiliser l'utilitaire csplit
pour fractionner une expression régulière, par exemple.
csplit -z file.csv '/^[0-9]\+,/' '{*}'
80
42
(les comptes indiquent le nombre de caractères sortis dans chaque fichier - vous pouvez les supprimer en ajoutant l'option -s
).
Les fichiers de sortie sont nommés xx00
, xx01
etc. par défaut - il existe des options pour modifier le préfixe et le suffixe si vous le souhaitez.
Ex.
$ csplit -z file.csv '/^[0-9]\+,/' '{*}'
80
42
$ head xx*
==> xx00 <==
1,'someval','otherval',,,,,
'','someotherval','some_otherval',,,,,
1BSD,'',,,,,
==> xx01 <==
2,'val',,,,,
,,,,,,
2BSD,,,,,,
2BCD,,,,,,
Je voulais voir tout ce que je pouvais faire avec sed
et j'ai réussi à en faire beaucoup. Nous pouvons écrire des fichiers avec sed
en utilisant les commandes w
et W
, mais je ne pouvais pas trouver un moyen d'écrire un fichier différent à chaque itération d'une boucle sed
, j'ai donc dû utiliser une boucle Shell. sed
est probablement le mauvais outil à utiliser pour ce travail, et il existe probablement un moyen plus agréable de le faire avec sed
. Quoi qu'il en soit, voici ce que je suis venu avec:
#!/bin/bash
sed ':a;N;s/\n/\x00/; ta' input | sed -r 's/\x00([0-9]+(,|\x00|$))/\n\1/g' > edited
n=0
while [ -s edited ]; do
((n++))
sed -n '1p' edited > csv-"$n"
sed -i '1d' edited
done
sed -i 'y/\x00/\n/' csv-*
rm edited
remplacez les nouvelles lignes par le caractère nul \x00
en utilisant une boucle sed
. Ceci afin que nous puissions utiliser les nouvelles lignes comme séparateurs significatifs ultérieurement.
sed ':a;N;s/\n/\x00/; ta' input
dirige le résultat et ajoute des nouvelles lignes avant les entiers qui étaient dans le premier champ, et écrit le résultat dans un fichier, edited
| sed -r 's/\x00([0-9]+(,|\x00|$))/\n\1/g' > edited
initialiser une variable à incrémenter
n=0
tant que edited
n'est pas vide, fais les choses
while [ -s edited ]; do
incrémenter n
((n++))
écrire la première ligne de edited
dans un nouveau fichier csv-$n
où $n
est la valeur actuelle de n
sed -n '1p' edited > csv-"$n"
supprimer la première ligne de edited
sed -i '1d' edited
c'est la fin de la boucle, et comme nous avons seulement une ligne pour chaque fichier que nous voulons écrire, ce n'est pas aussi lent que de traiter chaque ligne du fichier d'origine dans une boucle, mais quand même, c'est lent!
pour chaque fichier créé, reconvertissez les caractères nuls en nouvelles lignes
sed -i 'y/\x00/\n/' csv-*
supprimer le fichier intermédiaire
rm edited