IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

Remplacer certaines virgules dans un fichier (avec sed ?)


Sujet :

Shell et commandes GNU

  1. #1
    Membre éprouvé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2003
    Messages
    1 309
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 309
    Par défaut Remplacer certaines virgules dans un fichier (avec sed ?)
    Bonjour,

    j'ai un fichier csv dont le séparateur est une virgule. je voudrais le transformer en csv avec point-virgule pour séparateur. Mon problème est qu'il contient des chaînes avec des virgules. Exemple de ligne :
    "a,b,c,d",e,f,g,"h,i",j
    Il faudrait que je le transforme en :
    "a,b,c,d";e;f;g;"h,i";j

    J'ai essayé avec la commande sed mais je n'arrive à rien de bien.

    Quelqu'un sait comment faire ?

  2. #2
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 292
    Par défaut
    Bonjour

    Répondre à côté de la question est tout un art. Je m'y essaie:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ cat antivirgule
    "a,b,c,d",e,f,g,"h,i",j
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ awk -F',' '{etat=0; for (i=1;i<NF;i++) {if ($i ~ "\"") etat=1-etat; printf $i; if (!etat) printf ";"; else printf",";};printf $NF"\n";}' antivirgule
    "a,b,c,d";e;f;g;"h,i";j

  3. #3
    Membre éprouvé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2003
    Messages
    1 309
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 309
    Par défaut
    Pas du tout à côté, c'est exactement ce dont j'ai besoin.
    Merci.

  4. #4
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 292
    Par défaut
    OK. Attention quand même aux cas particuliers: double quotes à l'intérieur des doubles quotes, nombre impair de double quotes, champ entre double quotes mais sans virgule, etc.

  5. #5
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    Citation Envoyé par Flodelarab Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ awk -F',' '{etat=0; for (i=1;i<NF;i++) {if ($i ~ "\"") etat=1-etat; printf $i; if (!etat) printf ";"; else printf",";};printf $NF"\n";}' antivirgule
    "a,b,c,d";e;f;g;"h,i";j
    yep, et à mon avis ce sera difficile d'avoir un truc plus rigoureux sans avoir recours à un vrai gros parser avec sa grammaire etc., en mode vite fait bien fait c'est le mieux qu'on puisse faire

  6. #6
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    Tu peux utiliser csvtool (à installer au besoin), par contre il sucrera au passage les double quotes devenus inutiles (mais d'un autre coté, il en ajoutera si nécessaire et gère aussi l'échappement):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    csvtool -t "," -u ";" cat <(echo '"a,b,c,d",e,f,g,"h,i",j')
    a,b,c,d;e;f;g;h,i;j
     
    csvtool -t "," -u ";" cat <(echo '"a;b,c,d",e;f,g,"h,i",j')
    "a;b,c,d";"e;f";g;h,i;j
     
    csvtool -t "," -u ";" cat <(echo '"a,b"",c,d",e;f,g,"h,i",j')
    "a,b"",c,d";"e;f";g;h,i;j

  7. #7
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 292
    Par défaut
    Une version sed pour répondre à la question initiale.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ sed 's@"[^"]*"@\n&\n@g;:z1;s@\n\([^"][^\n]*\)\?,\(.*\n\)\?@\n\1;\2@g;t z1;s/\n//g' antivirgule                                            
    "a,b,c,d";e;f;g;"h,i";j
    On utilise \n comme marqueur, puisque forcément absent de l'espace de travail.
    Et on cherche \n ... , ... \n sans quotes, pour le remplacer.

  8. #8
    Membre chevronné
    Profil pro
    Inscrit en
    Août 2010
    Messages
    345
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 345
    Par défaut
    Bonjour,
    Peut être ce sed
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sed 's/"[^"]*"/\n&\n/g;:A;s/\(\n[^\n"]*\),/\1;/;tA;s/\n//g'
    Cordialement.

  9. #9
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 349
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 349
    Par défaut
    Et si à l'intérieur d'une paire de guillemet, on avait un retour à la ligne (donc, en fait les 2 lignes ne sont qu'une seule ligne csv) ?

  10. #10
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 292
    Par défaut
    Citation Envoyé par disedorgue Voir le message
    Et si à l'intérieur d'une paire de guillemet, on avait un retour à la ligne (donc, en fait les 2 lignes ne sont qu'une seule ligne csv) ?


    csvtool fonctionne.

    Quand à sed, ça ne fonctionnera pas. Mais ça n'empêche pas moins qu'il ne peut y avoir de \n dans l'espace de travail sed sans l'y faire rentrer volontairement.
    Donc on peut utiliser \n comme comme marqueur. Préférable à TOTO ou POUET ou ";" qui peuvent toujours exister dans le fichier.

  11. #11
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 349
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 349
    Par défaut
    Mais si, un exemple améliorable - ne gère pas correctement la dernière ligne (au sens csv) si elle n'est pas valide (manque le guillemet fermant) - :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ cat tt.csv
    "a,b,c,d",e,f,g,"h,i",j
    "a,b,
    c,d",e,f,g,"h,
    i",j
    "a,b,\"c\",d",e,f,g,"h,i",j
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    $ cat tt.sed
    #!/bin/sed -f
    s/^/ /
    :deb
     s/\([^\\]\)"/\1\n/
     trc
     bfin
    :rc
     s/\([^\\]\)"/\1\n\n/
     tdeb
     s/$/\n\n/
     N
     brc
    :fin
     s/\([^\n]\n\{2\}[^\n]*\),/\1;/
     tfin
     s/\([^\n]\)\n\{1,2\}\([^\n]\)/\1"\2/g
     s/ //
     s/\n\n\n/\n/g
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ ./tt.sed tt.csv
    "a,b,c,d";e;f;g;"h,i";j
    "a,b,
    c,d";e;f;g;"h,
    i";j
    "a,b,\"c\",d";e;f;g;"h,i";j

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Rechercher plusieurs mots dans un fichier avec sed
    Par DevServlet dans le forum Shell et commandes GNU
    Réponses: 4
    Dernier message: 26/01/2012, 14h40
  2. Réponses: 3
    Dernier message: 30/03/2011, 13h47
  3. copie contenu d'un fichier dans un autre fichier avec sed
    Par zorooo dans le forum Shell et commandes GNU
    Réponses: 14
    Dernier message: 18/01/2010, 09h17
  4. Réponses: 3
    Dernier message: 24/03/2009, 14h08
  5. Réponses: 2
    Dernier message: 07/04/2007, 11h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo