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 :

[bash] Modifier la valeur du premier champ d'une ligne si elle existe déjà


Sujet :

Shell et commandes GNU

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 25
    Par défaut [bash] Modifier la valeur du premier champ d'une ligne si elle existe déjà
    Bonjour,

    J'ai un fichier CSV contenant des lignes commençant par un nombre, en voici un extrait simplifié :
    "5","Lorem","ipsum",
    "6","dolor","sit"
    "7","amet","consectetur"
    "8","adipiscing","elit."
    "9","Sed","non"
    "10","risus.","Suspendisse"
    "11","lectus","tortor,"
    "1","dignissim","sit"
    "10","amet,","adipiscing"
    "11","nec,","ultricies"
    "6","sed,","dolor."
    On voit que le premier champ contient un nombre. Mais les trois derniers sont déjà présents plus haut dans le fichier ; ce sont ceux-là que je voudrais transformer, en les incrémentants. Voici le résultat que je souhaiterais obtenir :
    "5","Lorem","ipsum",
    "6","dolor","sit"
    "7","amet","consectetur"
    "8","adipiscing","elit."
    "9","Sed","non"
    "10","risus.","Suspendisse"
    "11","lectus","tortor,"
    "1","dignissim","sit"
    "12","amet,","adipiscing"
    "13","nec,","ultricies"
    "14","sed,","dolor."
    Mais je sèche. Ça dépasse mes capacités en shell. Pour l'instant, j'arrive simplement à récupérer tous les premiers champs, mais je ne sais pas quoi en faire après :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while read ligne; do
        echo $ligne | cut -f1 -d ","
    done < $fichier
    Un plus expert que moi pourrait-il trouver une solution ?

    Cordialement,
    Sémhur

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

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

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk 'BEGIN{FS=",";OFS=FS;} {$1=substr($1,2,length($1)-2);} (a[$1]>0){$1=max;} {a[$1]++;if ($1>=max) max=$1+1;} {$1="\""$1"\"";} 1'
    La deuxième et la cinquième accolades servent à enlever et remettre les doubles quotes, supposés toujours présents.
    Le tableau "a" stocke le nombre de fois qu'un motif est vu.
    "max" est le prochain indice libre à utiliser pour dédoublonner.

    Toute la numérotation peut être possiblement décalée.
    Mais il semble que ce soit ce que tu veux.

  3. #3
    Invité
    Invité(e)
    Par défaut
    c'est bizarre de faire une "renumérotation" à la volée
    et je ne vois pas où tu testes que l'indice est déjà utilisé :callim2:

    j'aurais attendu d'avoir lu tout le fichier pour connaître la valeur maximale de l'indice, et marquer les doublons, pour, dans l'action END, traiter le tableau et incrémenter les doublons*...

    *n'y a-t-il que des doublons, ne peut-il y avoir des "triplons", voire plus

  4. #4
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    3 018
    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 : 3 018
    Par défaut
    Si la première colonne n'est pas associée à quelque chose en particulier (comme le laisse présager le fait qu'il y a des doublons), pourquoi ne pas carrément la virer et la remplacer en utilisant NR:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk -F, -v OFS=, '{$1="\""NR"\""}1' file
    Y a-t-il une raison quelconque de conserver ces valeurs? S'agit il de corriger une ânerie commise à partir des premiers doublons, et dans ce cas le reste doit être gardé tel quel?

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 25
    Par défaut
    Waouh.
    C'est là que je me dis que j'ai une grosse marge de progression en shell et ses outils...

    Il y a juste un problème que je ne m'explique pas : on perd la première ligne ?
    Pour contourner, j'en ajoute une vide au début, mais je suppose qu'il y a moyen de faire plus propre.

    Voici mon code maintenant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    sed -i "1i\\n" $fichier
    while read ligne; do
        awk 'BEGIN{FS=",";OFS=FS;} {$1=substr($1,2,length($1)-2);} (a[$1]>0){$1=max;} {a[$1]++;if ($1>=max) max=$1+1;} {$1="\""$1"\"";} 1' >> tempfile
    done < $fichier
    mv tempfile $fichier

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 25
    Par défaut
    @N_BaH : ici il n'y a que des doublons, mais en effet dans un autre fichier j'ai potentiellement des triplons (jusqu'à des septuplons, en fait).

    @CosmoKnacki : Les valeurs de la première colonne sont a conserver. Ce sont des ID. Pour les doublons, je leur affecte un nouvel ID non encore utilisé.

  7. #7
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Semhur
    Voici mon code maintenant :
    mais, comment ça marche ?! il n'y a pas d'entrée pour awk.

    il n'y a pas besoin de lire le fichier ligne par ligne en shell pour utiliser awk : il sait lire des fichiers, même plusieurs, tout seul.

    Citation Envoyé par Semhur
    Pour les doublons, je leur affecte un nouvel ID non encore utilisé.
    c'est-à-dire ? il faudrait aussi trouver des manques dans la numérotation pour les attribuer d'abord aux doublons, et quand/si il n'y en a plus/pas, on utilise un indice supérieur à l'indice max ?

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 308
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while read ligne; do
        awk 'BEGIN{FS=",";OFS=FS;} {$1=substr($1,2,length($1)-2);} (a[$1]>0){$1=max;} {a[$1]++;if ($1>=max) max=$1+1;} {$1="\""$1"\"";} 1' >> tempfile
    done < $fichier
    Tout de suite après avoir posté, j'ai eu peur de voir quelque chose comme ça.
    Non seulement tu n'as pas besoin du while, puisque c'est ce que fait awk, travailler ligne à ligne; Mais, en plus, cela ne marche pas du tout ! Car la mémoire est perdue entre 2 lignes.

    Ce qui était attendu comme code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    awk 'BEGIN{FS=",";OFS=FS;} {$1=substr($1,2,length($1)-2);} (a[$1]>0){$1=max;} {a[$1]++;if ($1>=max) max=$1+1;} {$1="\""$1"\"";} 1' fichier
    "5","Lorem","ipsum",
    "6","dolor","sit"
    "7","amet","consectetur"
    "8","adipiscing","elit."
    "9","Sed","non"
    "10","risus.","Suspendisse"
    "11","lectus","tortor,"
    "1","dignissim","sit"
    "12","amet,","adipiscing"
    "13","nec,","ultricies"
    "14","sed,","dolor."
    Et rien de plus !


    je leur affecte un nouvel ID non encore utilisé.
    Ah ! C'est N_BaH qui a raison. Il faut lire tout le fichier pour avoir un premier bilan.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $ awk 'BEGIN{FS=",";OFS=FS;} (FNR==NR){a[$1]++;if (a[$1]==2) b[$1]=NR;v=int(substr($1,2,length($1)-2));if (max<v) max=v;next;} ((a[$1]>1)&&(FNR>=b[$1])){max++;$1="\""max"\"";} 1' fichier fichier
    "5","Lorem","ipsum",
    "6","dolor","sit"
    "7","amet","consectetur"
    "8","adipiscing","elit."
    "9","Sed","non"
    "10","risus.","Suspendisse"
    "11","lectus","tortor,"
    "1","dignissim","sit"
    "12","amet,","adipiscing"
    "13","nec,","ultricies"
    "14","sed,","dolor."

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 25
    Par défaut
    Ok, ça fonctionne ! Merci beaucoup, je passe la discussion en Résolue.

    J'ai essayé de comprendre dans le détail, mais je n'ai pas réussi
    En gros, ce que j'ai compris :
    * le (FNR==NR) permet de travailler sur le fichier et sur l'équivalent d'une copie, ça permettra de conserver la mémoire du nombre max.
    * les tableaux a et b, là je n'ai pas tout pigé. Le b sert à conserver le n° de ligne du max trouvé ?
    * la suppression et réinsertion des guillemets, c'est grâce à int(substr($1,2,length($1)-2)); et $1="\""max"\"";

    Mais si tu as un peu de temps pour expliquer, je suis preneur

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

Discussions similaires

  1. Modifier la valeur d'un champs dans une table mysql en fonction du temps.
    Par VaSss dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 03/05/2010, 11h30
  2. Réponses: 0
    Dernier message: 02/12/2008, 09h34
  3. Réponses: 2
    Dernier message: 29/06/2008, 19h16
  4. Modifier les valeurs de certains champs d'une table
    Par Xorbane dans le forum Requêtes et SQL.
    Réponses: 6
    Dernier message: 22/10/2007, 22h10
  5. Réponses: 4
    Dernier message: 07/08/2006, 16h19

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