Forum Linux.débutant comparaison de fichier avec clefs

Posté par . Licence CC by-sa
Tags : aucun
1
18
jan.
2018

Bonjour,

J'ai 2 fichiers avec différentes colonnes (séparateur étant la tabulation). la colonne 1 étant la clefs de chaque fichier.
fichier1:
e 12
f 2
j 20
z 5
l 6
o 7
b 4

fichier2:
a 4
d 2
j 4
k 5
l 6
o 8
b 4

Je souhaiterai avoir en qqles lignes avoir:
- les lignes apparaissent dans fichier1 et pas dans fichier2.
- les lignes apparaissent dans fichier2 et pas dans fichier1.
- les lignes en commun.

en utilisant cette ligne de commande

awk 'NR == FNR{ligne[$1]=1} NR != FNR {if(($1 in ligne))print $0 ligne[$2]}' fichier1 fichier2
ou
awk 'NR == FNR{ligne[$1]=1} NR != FNR {if(($1 in ligne))print $0 ligne[$2]}' fichier2 fichier1

je parviens à mes fins pour les 2 premiers besoins.

En revanche, pour les lignes avec la clef commune, je souhaiterai afficher

clefs valeur_fichier1 valeur_fichier2 mais je n'arrive pas à parvenir à cela avec cette ligne par exemple:

awk 'NR == FNR{ligne[$1]=1} NR != FNR {if(($1 in ligne))print $0 ligne[$0]}' fichier1 fichier2

en fait je ne sais pas comment printer la colonne 2 du tableau ligne…

merci

  • # join

    Posté par . Évalué à 5 (+4/-0).

    ça ne répond pas à ta question, mais join est fait pour ça

    $ join <(sort < fichier1) <(sort < fichier2)
    b 4 4
    j 20 4
    l 6 6
    o 7 8
    
    • [^] # Re: join

      Posté par . Évalué à 1 (+0/-0).

      effectivement ca ne répond pas à la question.. mais je vais toutefois utiliser cette ligne.
      Pour aller plus loin, j'ai besoin de faire des différences relatives entre les valeurs communes et n'afficher que celles qui sont > à 5% (en valeur absolue).

      du coup, en utilisant ton code, je souhaite faire
      si abs((valeur3-valeur2)/valeur2)*100) > 5 alors affichons clef valeur 1 valeur 2 diff sinon rien.

      pourrais tu m'aider stp ?

      • [^] # Re: join

        Posté par . Évalué à 1 (+0/-0).

        Les utilitaires texte join ou comm ne permettent pas de faire des calculs, donc awk est en effet tout indiqué. Je suis loin de le maîtriser assez pour t'aider, désolé.
        Est ce que tes deux fichiers ci-dessus sont des extraits des données à traiter?

  • # comm

    Posté par . Évalué à 5 (+3/-0).

    la commande comm est faite pour ça

    • [^] # Re: comm

      Posté par . Évalué à 1 (+0/-0).

      pas tout à fait, comm opère sur les lignes, et join sur des champs des lignes (ce qui semble être la demande initiale)

  • # man awk

    Posté par . Évalué à 3 (+2/-0).

    J'aime bien awk, alors je vais te guider un peu en espérant que tu apprennes à aimer awk.

    Les 2 lignes awk que tu donnes ne font pas ce que tu demandes.
    Elles affichent les clefs communes aux 2 fichiers avec la valeur de la clef dans le second fichier.
    Dans les 2 cas, tu reçois j, l, o et b.

    Découpons

    La 1re partie lit tout le premier fichier en mémoire dans un tableau et enregistre les clefs sans les valeurs (la valeur est = 1)
    NR == FNR{ligne[$1]=1}

    La 2e partie
    NR != FNR {…}
    est exécutée quand awk passe au 2e fichier. FNR recommence à 1 et NR continue sa progression.
    Si la clef de la ligne du fichier 2 se trouve dans le tableau, on imprime la ligne.
    Note que ligne[$2] est vide. Pax exemple sur la ligne "j 4", awk trouve ligne[j], mais ligne[4] n'existe pas.

    Il manque une négation dans le test :
    awk 'NR == FNR{ligne[$1]=1} NR != FNR {if(!($1 in ligne))print}' fichier1 fichier2
    a 4
    d 2
    k 5

    Pour les lignes à clef commune, le test initial est le bon et pour avoir les 2 valeurs, il suffit d'avoir stocké la valeur au lieu de 1.

    awk -v OFS="\t" 'NR == FNR{ligne[$1]=$2} NR != FNR {if(($1 in ligne))print $1, ligne[$1], $2}' fichier1 fichier2
    j 20 4
    l 6 6
    o 7 8
    b 4 4

    • [^] # Re: man awk

      Posté par . Évalué à 1 (+0/-0).

      Bonsoir,

      Oui il y avait une coquille dans mes commandes mais ç est rectifié :) du coup j'ai utilisé ce que tu m'as indiqué et cela fonctionne super bien. Encore merci pour l'aide!

Envoyer un commentaire

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.