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] Comparer deux fichiers csv


Sujet :

Shell et commandes GNU

  1. #21
    Membre éprouvé
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    792
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 792
    Points : 1 206
    Points
    1 206
    Par défaut
    Citation Envoyé par Flodelarab Voir le message
    Non. FNR et NR ne sont égaux que pour le premier fichier en entrée. Pour le second, NR retombe à 0 et FNR poursuit sa route.

    C'est pour cela que next est inutile et que la seconde accolade n'a pas besoin de condition. En effet, l'instruction "for i in ..." s'applique aux indices et pas aux valeurs. Aucun indice du tableau n'est un port puisque ce sont les adresses.


    Les indices sont précisément les numéros de port.($2 deuxième champ du premier fichier lu par awk).

    La condition de la deuxième instruction est indispensable. C'est elle qui permet d'imprimer les adresses (valeur du tableau a) ayant un numéro de port comme indice. La condition proposée par N_BaH était correcte. Elle pouvait aussi simplement s'écrire a[$1] qui s'évalue à TRUE si cet indice (port) existe dans le premier fichier.

    Enfin, l'instruction next est également indispensable pour "boucler" sur la première instruction et sa condition FNR==NR et d'ainsi rester sur le premier fichier. Sans elle, la deuxième instruction serait inutilement exécutée pour toutes les lignes du premier fichier. C'est la raison pour laquelle ok.Idriss a dû supprimer les doublons dans son test plus haut.

    Quant à la rapidité d'exécution, tout dépend du contexte et de la taille des fichiers. Y-a-t-il plusieurs lignes dans le fichier port? Risque t'on de retrouver des numéros de port dans les adresses mac (grep inutilisable)?
    :q :q! :wq :w :w! :wq! :quit :quit! :help help helpquit quit quithelp
    :quitplease :quitnow :leave :shit ^X^C ^C ^D ^Z ^Q QUITDAMMIT
    Jabber: ripat at im.apinc.org

  2. #22
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 286
    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 286
    Points : 12 742
    Points
    12 742
    Par défaut
    Pourquoi grep serait-il inutilisable ???
    Rien n'empêche de réécrire à la volée le fichier de port pour créer le bon pattern et de dire au grep de prendre comme fichier de pattern, l'entrée standard (voir l'une des solution de flodelarab)
    Cordialement.

  3. #23
    Membre éprouvé
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    792
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 792
    Points : 1 206
    Points
    1 206
    Par défaut
    Citation Envoyé par disedorgue Voir le message
    Pourquoi grep serait-il inutilisable ???
    Rien n'empêche de réécrire à la volée le fichier de port pour créer le bon pattern et de dire au grep de prendre comme fichier de pattern, l'entrée standard (voir l'une des solution de flodelarab)
    Certes mais à quel coût? Combien de pipe ou sous-process? Ça me rappelle une réponse un brin humoristique d'un modérateur du forum unix.com
    Also, whenever you're doing grep | grep | awk | kitchen | sink, you should just replace it all with one simple awk command.
    :q :q! :wq :w :w! :wq! :quit :quit! :help help helpquit quit quithelp
    :quitplease :quitnow :leave :shit ^X^C ^C ^D ^Z ^Q QUITDAMMIT
    Jabber: ripat at im.apinc.org

  4. #24
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 286
    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 286
    Points : 12 742
    Points
    12 742
    Par défaut
    On est d'accord sur le fond, ici, on aurait:
    sed | grep | cut
    Techniquement, on ne parserait qu'une seule fois le fichier mac_port.
    Pour le fichier port, on le parse au moins une fois pour la mise en forme. puis formatage de la sorti par cut. Bizarrement, un grep+cut est aussi rapide qu'un sed qui fait la même chose (tout au moins sur des fichiers de mille lignes environ).

    En awk, on est a peu près équivalent, car il est obligé de lire au moins un fois chaque fichier, il y a donc au moins une mise en forme (donnée de parsing) et les données à parser + la mise en forme pour la sortie.

    Après, selon la regex, il n'est pas impossible que la méthode par le grep puisse prendre la main...
    Cordialement.

  5. #25
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 459
    Points
    13 459
    Par défaut
    Citation Envoyé par ripat Voir le message
    Les indices sont précisément les numéros de port.($2 deuxième champ du premier fichier lu par awk).
    Levons l'ambiguïté: quand on se trouve dans la deuxième accolade pour le premier fichier, a[$1] utilise pour indice les adresses (00.1F.FF.5H.66) et n'a aucune chance de correspondre.
    Citation Envoyé par ripat Voir le message
    La condition de la deuxième instruction est indispensable.
    Elle est inutile. Que la confrontation ait lieu dans l'accolade ou avant l'accolade ne m'empêche pas de dormir.
    Citation Envoyé par ripat Voir le message
    La condition proposée par N_BaH était correcte. Elle pouvait aussi simplement s'écrire a[$1] qui s'évalue à TRUE si cet indice (port) existe dans le premier fichier.
    Elle est incorrecte car elle est toujours vraie alors que a[$1] n'est pas toujours vraie. Tu le dis toi-même
    Citation Envoyé par ripat Voir le message
    Sans elle, la deuxième instruction serait inutilement exécutée pour toutes les lignes du premier fichier.
    D'accord.
    Citation Envoyé par ripat Voir le message
    Quant à la rapidité d'exécution, tout dépend du contexte et de la taille des fichiers.
    On ne peut parler que de la vitesse algorithmique....
    Si tu commences à comparer le nombre de lignes, les microprocesseurs, etc, on n'est pas arrivé.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Also, whenever you're doing grep | grep | awk | kitchen | sink, you should just replace it all with one simple awk command.
    awk sait tout faire mais il le fait mal. grep ne sait que filtrer mais il le fait bien.
    Cf les temps que j'ai indiqué plus haut.


    Toutes ces choses étant dites, la méthode awk donnée ici est mauvaise car elle présuppose qu'il n'y a qu'une adresse par port. Ce qui paraît douteux. (L'inverse serait tout aussi douteux)
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  6. #26
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 459
    Points
    13 459
    Par défaut
    Non seulement il ne marche pas car l'association est douteuse, mais en plus, il y a un espace entre le ";" et le port qui fait que les deux ne correspondront jamais. Il faut proposer une solution du style:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ awk -F';' '(FNR==NR){plouf=" "$1;a[plouf]++} (FNR>NR){if ($2 in a) print $1}' filtre.txt initial.txt
    00.1F.FF.5H.66
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ awk -F'; ' '(FNR==NR){a[$1]++} (FNR>NR){if ($2 in a) print $1}' filtre.txt initial.txt
    00.1F.FF.5H.66
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  7. #27
    Membre éprouvé
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    792
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 792
    Points : 1 206
    Points
    1 206
    Par défaut
    Citation Envoyé par Flodelarab Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ awk -F'; ' '(FNR==NR){a[$1]++} (FNR>NR){if ($2 in a) print $1}' filtre.txt initial.txt
    00.1F.FF.5H.66
    Tu pourrais te passer de la condition de la deuxième instruction en utilisant l'instruction next dans la lecture du premier fichier. De plus cette condition n'est pas correcte. FNR>NR s'évaluera toujours à FALSE. FNR ne sera jamais supérieur à NR dans la lecture de fichiers multiples. Impossible.

    La construction:awk 'FNR==NR{instruction pour fichier1; next} {instruction pour fichier2}' fichier1 fichier2 est un grand classique de lecture de fichier multiple.

    Un peu de lecture:
    http://www.unix.com/shell-programmin...oduce-3rd.html
    http://www.staff.science.uu.nl/~oost...k/nawk_77.html
    http://www.catonmat.net/blog/ten-awk...k_be_idiomatic
    :q :q! :wq :w :w! :wq! :quit :quit! :help help helpquit quit quithelp
    :quitplease :quitnow :leave :shit ^X^C ^C ^D ^Z ^Q QUITDAMMIT
    Jabber: ripat at im.apinc.org

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 459
    Points
    13 459
    Par défaut
    Oui FNR<NR et pas FNR>NR

    T'as trouvé la bonne faute pour une méthode qui de toute façon ne marche pas. (cf plus haut plusieurs adresses pour un seul port)
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  9. #29
    Membre éprouvé
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    792
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 792
    Points : 1 206
    Points
    1 206
    Par défaut
    Citation Envoyé par Flodelarab Voir le message
    Oui FNR<NR et pas FNR>NR

    T'as trouvé la bonne faute pour une méthode qui de toute façon ne marche pas. (cf plus haut plusieurs adresses pour un seul port)
    Si, si, c'est possible en aménageant un peu le code awk:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk -F' ; ' 'FNR==NR{a[$2]=a[$2] "\n" $1;next}a[$1]{printf a[$1]}' mac port
    :q :q! :wq :w :w! :wq! :quit :quit! :help help helpquit quit quithelp
    :quitplease :quitnow :leave :shit ^X^C ^C ^D ^Z ^Q QUITDAMMIT
    Jabber: ripat at im.apinc.org

  10. #30
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 286
    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 286
    Points : 12 742
    Points
    12 742
    Par défaut
    Alors plusieurs remarques:

    -Les méthodes avec le sed ne fonctionnent pas correctement, car l'expression régulière n'est pas tout à fait correcte, elle confont au niveau des ports la valeur 1 avec 10 à 19, 2 avec 20 à 29, etc...

    -Dans toutes les méthodes awk proposées, chez moi il n'y a que celle de N_BaH qui fonctionne où d'ailleurs on peut se passer de FNR==NR puisque le 2éme champs étant inexistant dans le fichier port, on ne risque pas d'écrasement de valeur et c'est d'ailleurs pour cela qu'elle fonctionne aussi avec l'erreur FNR=NR

    Pas testé les méthodes avec join, car potentiellement trop lente.

    Sinon, après correction de la regex coté sed (ou grep), la méthode awk à l'air plus rapide d'environ 25%... (mais bon, chez moi, je suis en cygwin, donc difficile à bien juger)
    Cordialement.

Discussions similaires

  1. [CSV] Comparer deux fichiers CSV
    Par Ghirahim dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 10
    Dernier message: 03/06/2015, 16h23
  2. Comparer deux fichiers csv
    Par kerplouz dans le forum Général Python
    Réponses: 1
    Dernier message: 21/11/2012, 21h17
  3. Comparer deux fichier
    Par Taz_8626 dans le forum Langage
    Réponses: 3
    Dernier message: 20/06/2006, 11h46
  4. comparer deux fichiers avec une api windows
    Par sweetdreamer dans le forum Windows
    Réponses: 4
    Dernier message: 25/05/2006, 22h10
  5. Fonction c qui compare deux fichiers ???
    Par babyface dans le forum C
    Réponses: 4
    Dernier message: 19/11/2005, 13h07

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