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 :

Comparaison de deux fichiers avec awk


Sujet :

Shell et commandes GNU

  1. #1
    Nouveau membre du Club
    Inscrit en
    Juin 2010
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Juin 2010
    Messages : 44
    Points : 34
    Points
    34
    Par défaut Comparaison de deux fichiers avec awk
    Bonjour , je souhaite comparer deux fichiers sur un champ bien précis . Les deux fichiers sont structurés avec des champs fixes pas de séparateur entre chaque champ.

    Sur le premier fichier ( par ex fichier1.txt) le champ qui m 'intéresse se trouve en position suivante : colonne de 1 à 8 .

    Sur le deuxième fichier ( par ex fichier2.txt) le champ qui m 'intéresse se trouve en position suivante : colonne de 13 à 21 .

    je souhaite donc comparer ces deux champ et afficher le résultat dans un fichier . comment je dois procéder merci de votre aide .

    j'ai fait un truc comme ça , ça ne marche pas très bien , une idée

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    awk ' { cle1=substr($0,1,8);   
                              if (cle1==cle2)
                    {
                                                   print $0
                    }
                    while  ((getline < "fichier2.txt") > 0) {
                                  cle2=substr($0,13,8);
                                                  if (cle1==cle2) 
                                   {
                                                   print $0
                                   }
                                 } 
    }'  fichier1.txt. > res.txt

  2. #2
    Expert confirmé
    Avatar de becket
    Profil pro
    Informaticien multitâches
    Inscrit en
    Février 2005
    Messages
    2 854
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Informaticien multitâches
    Secteur : Service public

    Informations forums :
    Inscription : Février 2005
    Messages : 2 854
    Points : 5 915
    Points
    5 915
    Par défaut
    Salut,
    En supposant que le séparateur est un point-virgule quelque chose comme ceci devrait faire l'affaire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     awk -F';' '{ getline Fichier2 < "/path/to/second-file" ; split(Fichier2,F2s,";") ; SF2=F2s[5]F2s[6]F2s[7] ; SF1=$5$6$7 ; if( SF1 !~ SF2 ) { print "DONT MATCH - " SF1 "#--##" SF2  } }' /path/to/first-file

  3. #3
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 392
    Points
    19 392
    Par défaut
    Bonjour,

    Les deux fichiers sont structurés avec des champs fixes
    gawk possède une variable FIELDWIDTHS.

    ça ne marche pas très bien
    c'est-à-dire ?
    quel est le comportement attendu ?
    quel est le comportement observé ?
    un échantillon représentatif des fichiers à traiter et la sortie correspondante seraient appréciés.
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  4. #4
    Nouveau membre du Club
    Inscrit en
    Juin 2010
    Messages
    44
    Détails du profil
    Informations forums :
    Inscription : Juin 2010
    Messages : 44
    Points : 34
    Points
    34
    Par défaut
    Re,
    voici un échantillon pour chaque fichier

    structure premier Fichier : aucun séparateur que des champs fixes, les valeurs sont tjs à la même position

    ex des données :

    00000001 0100122223
    00000002 0100122224
    00000003 0100122226

    le champ que je souhaite comparer avec le deuxième fichier est positionnée en gras se sont les 8 premiers caractères du fichier

    Struture du deuxième fichier : aucun séparateur que des champs fixes les valeurs sont tjs à la même position

    ex de données :

    L2204 01001 L ABERGEMENT CLEMENCIAT 0 101400L ABERGEMENT CLEMENCIAT
    V2204 0100100000001 CLEMENCIAT CLEMENCIAT N 000014000000 0000 0000 0000 00000
    V2204 0100100000002 BOIS LIEU DIT AU BOIS LD VVAN 000014000000 0000 0000 0000 00002
    V2204 0100100000003 CHAMAUDRY CHAMAUDRY N 000014000000 0000 0000 0000 00000

    Le champ que je souhaite comparer avec le premier fichier est tjs positionné de la colonne 13 à la colonne 20( taille 8)

    Donc ma demande , si le champ du premier fichier identifié en gras position de 1 à 8( ci-dessus) est présent dans le deuxième fichier(colonne13 à 20) , alors créer un fichier de résultat on y rajoutant la ligne du premier fichier
    Merci de votre aide

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

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

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    salut,

    la fonction substr() est ton amie, sur le même principe décrit par becket plus haut
    une façon de faire assez simple :
    Code script.awk : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #!/usr/bin/awk -f
     
    NR == FNR {  # on traite le 1er fichier, on rempli un tableau
       tab[substr($0, 1, 8)] = $0;
       next;
    }
     
    tab[substr($0, 12, 8)] { # on traite le 2nd fichier, pour chaque valeur on cherche dans le tableau
       print tab[substr($0, 12, 8)];
    }

    et le résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $ ./script.awk fichier1.txt fichier2.txt > res.txt
    $ cat res.txt
    00000001 0100122223
    00000002 0100122224
    00000003 0100122226

  6. #6
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2013
    Messages : 563
    Points : 460
    Points
    460
    Par défaut
    Salut,

    perso je ferai un truc du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # Traite le 1er fichier ligne par ligne
    while read LigneFichier1
    do
      # Traite le second fichier ligne par ligne pour chaque ligne du 1er fichier
      while read LigneFichier2
      do
        # Compare les valeurs des 2 fichiers et rempli le fichier de retour
        [[ ${LigneFichier1:0:8} == ${LigneFichier2:11:8} ]] && echo "${LigneFichier}" >> reply.txt
      done < fichier2.txt
    done < fichier1.txt
    ce qui me renvoie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    cat reply.txt
    00000001 0100122223
    00000002 0100122224
    00000003 0100122226
    mais bon ça ne répond pas vraiment à la question qui évoquait awk :p
    Sous Kubuntu 20.04

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

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

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    Citation Envoyé par hizoka Voir le message
    mais bon ça ne répond pas vraiment à la question qui évoquait awk :p
    surtout c'est beaucoup moins efficace étant donné que pour chaque ligne du fichier1 tu relis l'intégralité du fichier2

  8. #8
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2013
    Messages : 563
    Points : 460
    Points
    460
    Par défaut
    Oui oui, tout à fait, mais pour un fichier de 3 lignes ça va :p

    Mais sinon j'aurais fait la même chose que toi en python.

    Après rien n’empêche de le faire en bash aussi.

    Une boucle sur le fichier 2 pour remplir une liste avec les valeurs.
    Puis une boucle sur le fichier qui recherche sa valeur dans la liste.

    Enfin c'était plus pour le plaisir de faire un petit code en bash
    Sous Kubuntu 20.04

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

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

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    Citation Envoyé par hizoka Voir le message
    c'était plus pour le plaisir de faire un petit code en bash
    yep j'avais compris, j'ai mis un

    for fun une version bash :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/bin/bash
    declare -A tab  # tableau associatif
     
    while read line; do
       tab[${line%% *}]="$line"
    done < fichier1.txt
     
    while read line; do
       tmp=${tab[${line:11:8}]}
       if [ -n "$tmp" ]; then
          echo "$tmp"
       fi
    done < fichier2.txt > res.txt

  10. #10
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2013
    Messages : 563
    Points : 460
    Points
    460
    Par défaut
    J'aime lire ce genre de code, clair et bien pensé
    Sous Kubuntu 20.04

  11. #11
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 287
    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 287
    Points : 12 744
    Points
    12 744
    Par défaut
    Pour le fun:
    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
    $ cat /tmp/fic1
    00000001 0100122223 
    00000002 0100122224 
    00000003 0100122226 
    $ cat /tmp/fic2
    L2204 01001 L ABERGEMENT CLEMENCIAT 0 101400L ABERGEMENT CLEMENCIAT 
    V2204 0100100000001 CLEMENCIAT CLEMENCIAT N 000014000000 0000 0000 0000 00000 
    V2204 0100100000002 BOIS LIEU DIT AU BOIS LD VVAN 000014000000 0000 0000 0000 00002 
    V2204 0100100000003 CHAMAUDRY CHAMAUDRY N 000014000000 0000 0000 0000 00000 
     
    $ sed 's/\(.\{8\}\).*/^.\\{11\\}\1/' /tmp/fic1 | grep -v -f - /tmp/fic2  #ligne de fic2 avec champs non présent dans fic1
    L2204 01001 L ABERGEMENT CLEMENCIAT 0 101400L ABERGEMENT CLEMENCIAT 
     
    $ sed 's/\(.\{8\}\).*/^.\\{11\\}\1/' /tmp/fic1 | grep  -f - /tmp/fic2  #ligne de fic2 avec champs présent dans fic1
    V2204 0100100000001 CLEMENCIAT CLEMENCIAT N 000014000000 0000 0000 0000 00000 
    V2204 0100100000002 BOIS LIEU DIT AU BOIS LD VVAN 000014000000 0000 0000 0000 00002 
    V2204 0100100000003 CHAMAUDRY CHAMAUDRY N 000014000000 0000 0000 0000 00000
    Cordialement.

  12. #12
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2013
    Messages : 563
    Points : 460
    Points
    460
    Par défaut
    J'aurais vraiment pas pensé à foutre des commandes via le sed pour que le grep les utilise dans ses recherches...

    Le tout en une ligne même si niveau temps ça doit être un peu plus longs vu qu'il boucle sur tout le fichier (comme dans ma proposition).

    J'adore ce genre de topic !
    Sous Kubuntu 20.04

  13. #13
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 287
    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 287
    Points : 12 744
    Points
    12 744
    Par défaut
    Pas vraiment, il est vrai que c'est plus lent que la proposition awk de BufferBob, mais je ne lis qu'une fois le fichier 2 et disons, pour faire simple, 2 fois le fichier 1: pour le transformer via sed, et cette transformation n'est lu qu'une seule fois par grep qui l'utilise pour sa recherche.
    Tu peux voir ça comme un grep avec une énorme expression régulière de type A|B|C.
    Cordialement.

  14. #14
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2013
    Messages : 563
    Points : 460
    Points
    460
    Par défaut
    OK, j'avais mal compris, merci pour l'info
    Sous Kubuntu 20.04

Discussions similaires

  1. AWK table hashage et comparaison entre deux fichiers
    Par Shyma dans le forum Shell et commandes GNU
    Réponses: 33
    Dernier message: 26/06/2017, 16h06
  2. [Python 3.X] Comparaison de deux fichiers txt avec une reponse IDENTIQUE: oui ou non
    Par pascaljqt dans le forum Général Python
    Réponses: 5
    Dernier message: 28/07/2015, 23h09
  3. Comparaison deux fichiers avec cobol
    Par Babylone159 dans le forum Cobol
    Réponses: 5
    Dernier message: 03/09/2012, 12h36
  4. comparaison de deux fichiers textes avec un script python
    Par zekruss dans le forum Général Python
    Réponses: 1
    Dernier message: 10/11/2009, 05h52

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