Homogénéiser un fichier csv

Résolu
zigroful Messages postés 20 Date d'inscription dimanche 16 février 2020 Statut Membre Dernière intervention 29 août 2023 - Modifié le 28 août 2023 à 17:00
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 - 29 août 2023 à 11:18

Bonjour à tous,

je cherche depuis quelques jours une solution avec sed, awk ou bash à ce problème:

Je dispose d'un fichier csv de 5 champs et 300 enregistrements. Le séparateur des champs est un point-virgule.

Les champs ne sont pas tous remplis et là ou l'enregistrement est incomplet, les séparateurs ne figurent plus.

Exemple: voici en exemple

ET1;ET2;ET3;ET4;ET5
a1;a2;a3
b1
c1;c2;
d1;d2;d3;d4;

Je voudrait transformer ce tableau en :

ET1;ET2;ET3;ET4;ET5
a1;a2;a3;;
b1;;;;
c1;c2;;;
d1;d2;d3;d4;

... c'est-à-dire rétablir le nombre d'enregistrements par ligne (5 ici), en rajoutant autant de séparateurs (et de champs vides) qu'il faut.

Je ne trouve pas le moyen de répéter de manière paramétrée un caractère (ici ;) en fin de ligne de manière à reconstituer un enregistrement ayant le même nombre de champs que la ligne d'entête.

Quelqu'un aurait-il une idée sur la manière de s'y prendre en n'utilisant que awk, sed ou bash ?

A voir également:

5 réponses

dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
28 août 2023 à 16:58

hello

$ awk 'BEGIN {FS=OFS=";"} {NF=5; print $0}' fichier
ET1;ET2;ET3;ET4;ET5
a1;a2;a3;;
b1;;;;
c1;c2;;;
d1;d2;d3;d4;
2
mamiemando Messages postés 33081 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 27 avril 2024 7 749
28 août 2023 à 17:16

Élégant, j'aime :-)

0
zigroful Messages postés 20 Date d'inscription dimanche 16 février 2020 Statut Membre Dernière intervention 29 août 2023
28 août 2023 à 19:19

J’ai essayé cette méthode en redirigeant la sortie sur le fichier d’entree, mais ça donne comme résultat un fichier vide. En revanche quand la sortie est standard, tout va bien ! Je ne comprends pas pourquoi ça donne un fichier vide quand on redirige la sortie sur le fichier d’entree. 

0
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615 > zigroful Messages postés 20 Date d'inscription dimanche 16 février 2020 Statut Membre Dernière intervention 29 août 2023
29 août 2023 à 10:21

le fichier de sortie doit être différend du fichier d'entrée

0
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615 > dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024
Modifié le 29 août 2023 à 15:48

pour  modifier le fichier original (comme sed -i)

awk -i inplace 'BEGIN {FS=OFS=";"} {NF=5; print $0}' fichier

il faut gawk 4.1.0

chez moi awk==gawk

0
jee pee Messages postés 39661 Date d'inscription mercredi 2 mai 2007 Statut Modérateur Dernière intervention 28 avril 2024 9 240
28 août 2023 à 16:48

Bonjour,

Une méthode plus simple en utilisant Excel, ouvrir le CSV et le réenregistrer en un nouveau CSV, Excel devrait en faire un fichier cohérent.


0
mamiemando Messages postés 33081 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 27 avril 2024 7 749
Modifié le 28 août 2023 à 17:14

Bonjour,

Préliminaires

Il faudrait préciser deux trois aspects, notamment

  • Entrée : d'où sont lues les données d'entrées
    • Soit depuis un fichier donné, dont le nom est passé en paramètre
    • Soit depuis l'entrée standard
  • Sortie : où sont écrites les données corrigées
    • Dans le fichier d'entrée (modification en place, comme avec sed)
    • Dans un autre fichier
      • Soit dans un fichier donné, dont le nom est passé en paramètre
      • Soit vers la sortie standard
  • Je te recommande plutôt de lire sur l'entrée standard et d'écrire sur la sortie standard et de faire les éventuelles redirections avec les opérateurs < et > au moment d'appeler ton script.

Concernant le traitement lui-même, je suppose qu'on détermine le nombre de champs attendu à l'aide de la première ligne (et part du principe que les lignes suivantes en contienne au plus ce nombre).

En shell pur

Principe: on utilise cette syntaxe pour compter le nombre de ";". Ensuite il suffit à l'aide d'une boucle for d'écrire autant que fois que nécessaire les ";" manquants (tu peux utiliser seq) et on n'oublie pas de passer à la ligne (avec echo).

mon_script.sh :

#!/bin/bash

while read -r line; do
    echo -ne "$line"
    res="${line//[^;]}"
    n="${#res}"
    if [ -z "$expected" ];
    then
        expected="$n"
    fi
    if (( $n < $expected ));
    then
        for i in $(seq 1 $((expected - n)))
        do
            echo -ne ";"
        done
    fi
    echo ""
done

Ce programme s'utilise comme suit :

chmod a+x mon_script.sh
./mon_script.sh < data_in.txt > data_out.csv

En awk

Tu peux écrire un programme "plus naturel" qui pour chaque ligne compte le nombre de ";", puis écrit le nombre de ";" manquants. La syntaxe de awk étant proche de celle du C (en plus simple), il n'y a pas de grosse difficulté. Si tu pars sur awk, pas besoin d'autre chose (ni grep, ni sed, ni awk).

toto.awk

#!/usr/bin/awk -f

BEGIN {
    expected = -1;
}

{
    n = 0;
    for (i = 0; i < length($0); i++) {
        c = substr($0, i, 1);
        if (c == ";") {
            n++;
        }
    }
    if (expected < 0) {
        expected = n;
    }
    extra = "";
    for (i = 0; i < expected - n; i++) {
        extra = extra ";";
    }
    printf "%s%s\n", $0, extra
}

Utilisation :

chmod a+x toto.awk
./toto.awk < data_in.txt > data_out.csv

Bonne chance

0
zigroful Messages postés 20 Date d'inscription dimanche 16 février 2020 Statut Membre Dernière intervention 29 août 2023
28 août 2023 à 17:15

MILLE MERCI Dubcek !

0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
zigroful Messages postés 20 Date d'inscription dimanche 16 février 2020 Statut Membre Dernière intervention 29 août 2023
29 août 2023 à 10:01

Bonjour Dubceck

J’ai essayé cette méthode en redirigeant la sortie sur le fichier d’entree, mais ça donne comme résultat un fichier vide. En revanche quand la sortie est standard, tout va bien ! Je ne comprends pas pourquoi ça donne un fichier vide quand on redirige la sortie sur le fichier d’entree. 

0