2
votes

comment comparer les valeurs entre deux fichiers?

J'ai deux fichiers avec deux colonnes séparées par un espace

sdiff file1.txt file2.txt

Je veux comparer les valeurs de file1 column2 avec file2 column2 pour la même valeur dans column1. et n'imprimez que les valeurs qui existent dans le fichier1 colonne2 mais pas dans le fichier2 colonne2 le long et non l'inverse avec la valeur respective dans la colonne1

o / p souhaité

il ne devrait rien afficher pour 281475225437349 comme toutes les valeurs de fichier1 colonne2 présentes dans fichier2 colonne 2 pour 281475225437349

il ne doit imprimer que les valeurs pour 281475550885480 qui sont présentes dans fichier1 colonne2 mais pas présentes dans fichier2 colonne2. Comme les valeurs 57 et 99 pour 281475550885480

Donc, o / p fichier comme:

cat output.txt
281475550885480 57,99

J'ai essayé de trier le fichier et de comparer en utilisant sdiff mais cela donne différence et sa prise de temps

cat file1.txt
281475225437349 33,32,21,17,20,22,18,30,19,16,23,31
281475550885480 35,32,33,21,39,40,57,36,41,17,20,38,34,37,16,99

cat file2.txt
281475550885480 16,17,20,21,32,33,34,35,36,37,38,39,40,41
281475225437349 16,17,18,19,20,21,22,23,24,25,30,31,32,33


3 commentaires

J'ai ajouté une mise en forme à votre message pour le rendre plus facile à comprendre. Mais il semble y avoir une certaine répétition là-dedans. Pouvez-vous s'il vous plaît vérifier et supprimer tout texte en double.


Bienvenue à SO @Jeevan Patil, votre question n'est PAS claire. Veuillez mentionner 3 choses simples, 1-échantillon d'entrée, 2-échantillon de sortie et 3ème-tout ce que vous avez essayé afin de le corriger dans le bouton CODE TAGS {} et faites-le nous savoir.


Salut . Merci pour la suggestion. Je l'ai modifié et supprimé les déclarations en double


6 Réponses :


1
votes

Vous devez utiliser deux boucles dans votre code. Également diviser le caractère ',' et définir deux tableaux, après

foreach(var itemOne as arrayOne){
boolean isExist=false;
foreach(var itemTwo as arrayTwo)
if(itemOne==itemTwo) isExist=true;

if(isExist) console.log(itemOne+" is exist");
}


1 commentaires

Ressemble beaucoup à C #.



3
votes

Solution Perl: créez un hachage de hachages à partir du deuxième fichier. La clé est le grand nombre, les clés intérieures sont les plus petits nombres de la liste séparée par des virgules. Ensuite, parcourez le premier fichier et vérifiez quels numéros ne sont pas mentionnés dans la structure mémorisée.

281475225437349 24,25

BTW, lorsque vous changez de fichier, la sortie sera

#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

open my $f1, '<', 'file1' or die $!;
open my $f2, '<', 'file2' or die $!;

my %seen;
while (<$f2>) {
    my ($key, $value_string) = split ' ';
    my @values = split /,/, $value_string;  #/
    undef @{ $seen{$key} }{@values};
}
while (<$f1>) {
    my ($key, $value_string) = split ' ';
    my @values = split /,/, $value_string;
    my %surplus;
    undef @surplus{@values};
    delete @surplus{ keys %{ $seen{$key} } };
    say $key, ' ', join ',', keys %surplus
        if keys %surplus;
}

car 24 et 25 ne sont pas présents dans le fichier1.


9 commentaires

salut merci pour votre entrée. Mais ma version Perl est ancienne et ne prend pas en charge feature.pm. Je ne peux pas améliorer Perl. pouvez-vous suggérer une alternative?


@JeevanPatil: utilisez simplement print au lieu de dites et ajoutez un "\ n" .


Super .. l'impression fonctionne. Merci . Mais à quelle ligne dois-je ajouter "\ n"?


print $ key, '', (join ',', keys% surplus), "\ n" if keys% surplus;


cela a fonctionné comme prévu. Encore merci. Je viens de tomber sur le problème où dans le fichier2, la colonne 2 n'a aucune valeur pour un objet de la colonne 1 .. Comme ci-dessous ......


chat file1.txt 281475225437349 33,32,21,17,20,22,18,30,19,16,23,31 281475550885480 35,32,33,21,39,40,57,36,41,17,20 , 38,34,37,16,99 cat file2.txt 281475550885480 16,17,20,21,32,33,34,35,36,37,38,39,40,41 281475225437349 Donc o / p devrait être 281475225437349 33,32,21,17,20,22,18,30,19,16,23,31 281475550885480 57,99 Mais cela donne une erreur pour cette condition


il ne fonctionne pas avec ~ 1k valeurs dans column2. J'ai ~ 2k valeurs de 16 à 2016 dans column2 pour certains objets et cela ne fonctionne pas là-bas.


Oh, je vois, pour corriger l'erreur, ajoutez la condition if à undef @ {$ vu {$ key}} {@ values} if @values; .


Merci .. Cela fonctionne exactement. Je testerais ce script avec plus de scénarios. :)



0
votes

C'est simple avec awk:

awk '(NR==FNR) { a[$1]=$2; next }
     { delete b }                       # clear array
     { # split strings in number elements
       split($2,f,",");    for(i in f) f1[f[i]+0];
       split(a[$1],f,","); for(i in f) f2[f[i]+0]
     }
     { for(i in f1) if (! (i in f2)) b[i] }
     { c=$1" "; for(i in b) {printf c i; c="," }; if (c==",") printf "\n" }' file2 file1

qui renvoie:

281475550885480 57,99

L'idée est de stocker la chaîne de la colonne deux avec un deux supplémentaires pour vous assurer que chaque nombre est entre des virgules. Recherchez ensuite la sous-chaîne en sandwich.

Si vous devez faire une vérification des nombres réels et que vous devrez peut-être comparer les nombres "5" avec "005" et qu'ils devraient être égaux, alors vous devriez faire le suivant:

awk '(NR==FNR) { a[$1]=","$2","; next }
     { delete b }                   # clear array for new run
     { split($2,f,",") }            # split string of file1 in array f
     { for(i in f) if (! match(a[$1],"," f[i] ",")) b[f[i]]  }                                                                                                                                                                             
     { c=$1" "; for(i in b) {printf c i; c="," }; if (c==",") printf "\n" }' file2 file1


0 commentaires

0
votes

Cela pourrait fonctionner pour vous (GNU sed):

sed -r 's#^(\S+)\s(\S+)$#/^\1 /s/$/,\\n\2,/#' file2 |
sed -rnf - -e ':a;s/(\b[0-9]+,)(.*\n.*)\1/\2/;ta;s/(.*),\n.*/\1/p' file1

La solution peut être divisée en deux parties.

Le premier fichier2 est transformé en un script sed qui ajoute les valeurs de chaque clé à la même clé dans fichier1. Des , supplémentaires sont ajoutés pour faciliter la correspondance et serviront d'indicateur pour savoir si une ligne de fichier1 a des valeurs à imprimer.

Le script généré à partir de fichier2 est redirigé vers un le deuxième appel sed et un indice supplémentaire utilisent la substitution et une boucle pour supprimer les valeurs correspondantes du fichier1.

En cas d'échec de la correspondance, et parce que le deuxième appel sed utilise le commutateur -n pour rendre l'impression explicite, une correspondance finale supprime les valeurs introduites , et non correspondantes après la nouvelle ligne et imprime le résultat requis.


0 commentaires

0
votes
$ cat tst.awk
BEGIN { FS="[ ,]" }
NR==FNR {
    for (i=2; i<=NF; i++) {
        file2[$1,$i]
    }
    next
}
{
    diff = ""
    for (i=2; i<=NF; i++) {
        if ( !(($1,$i) in file2) ) {
            diff = (diff == "" ? "" : diff ",") $i
        }
    }
    if (diff != "") {
        print $1, diff
    }
}

$ awk -f tst.awk file2 file1
281475550885480 57,99

0 commentaires

1
votes

un autre awk

$ awk -v c=, 'NR==FNR {a[$1]=$2; next}
                      {for(i=2;i<=NF;i++) 
                         {if(c a[$1] c !~ c $i c) p=(p==""?$1" ":p c) $i} 
                          if(p) print p; p=""}' file2 FS=' |,' file1

281475550885480 57,99


0 commentaires