Vergleichen Sie zwei Dateien basierend auf dem Schlüssel und drucken Sie den Wertunterschied in einer anderen Datei im Bash-Shell-Skript

Vergleichen Sie zwei Dateien basierend auf dem Schlüssel und drucken Sie den Wertunterschied in einer anderen Datei im Bash-Shell-Skript

Brauche Hilfe bei einem Shell-Skript. Ich habe 2 große Dateien mit jeweils ca. 1,2 GB Daten, mit Schlüssel und Werten. Ich muss beide Dateien anhand des Schlüssels vergleichen und den Unterschied zwischen dem Wert in der dritten Datei und dem eindeutigen Wert in Datei 1 speichern.

Datei 1:

test1 marco;polo;angus
test2 mike;zen;liza
test3 tom;harry;alan
test4 bob;june;janet

Datei 2:

test1 polo;angus
test2 mike
test4 bob;janet

Ich möchte die ersten beiden Spalten von Datei1 mit Datei2 vergleichen (den gesamten Inhalt von Datei2 in den ersten beiden Spalten durchsuchen) und bei Übereinstimmung die Wertedifferenz drucken. Dann nach der zweiten Zeile von Datei 1 suchen und so weiter. Auch in Datei 1 eindeutige Schlüssel sollten gedruckt werden.

Erwartete Ausgabe:

test1 marco
test2 zen;liza
test3 tom;harry;alan
test4 june

Die Dateien, die ich habe, sind riesig und enthalten etwa 100.000 Zeilen, daher möchte ich die Ausführung beschleunigen. Dies läuft in einem Shell-Skript, #!/usr/bin/env bash. beispielsweise mit:

1332239_44557576_CONTI Lased & Micro kjd $353.50_30062020_lsdf3_no-rule 343323H;343434311H;454656556H;343343432H 

Es ist eine einfache Textdatei mit diesem als Schlüssel ( 1332239_44557576_CONTI Lased & Micro kjd $353.50_30062020_lsdf3_no-rule) und diesen als Werten: ( 343323H;343434311H;454656556H;343343432H)

Datei 2 ist immer eine Teilmenge von Datei 1. Es müssen lediglich Werte (gegen Schlüssel) gefunden werden, die in Datei 2 nicht vorhanden sind, und eindeutige Werte in Datei 1.

Antwort1

Verwenden eines Perl-Skripts:

Angenommen, Sie suchenDatei2 basierend auf Datei1und nicht umgekehrt. Wenn Sie auch nach Datei1 basierend auf Datei2 suchen möchten, müssen Sieeine weitere For-Schleife hinzufügenfür das file2-Wörterbuch (Hash).
DataFiles:

$ cat file1.txt 
test1 marco;polo;angus
test2 mike;zen;liza
test3 tom;harry;alan
test4 bob;june;janet

$ cat file2.txt 
test1 polo;angus
test2 mike
test4 bob;janet

Skript :

#!/usr/bin/perl

use warnings;
use strict;

my $file1=$ARGV[0];
my $file2=$ARGV[1];
my %dict1;  #Stores file1 unique key and value pairs in this dictionary ( HASH in perl )
my %dict2;  #Stores file2 unique key and value pairs in this dictionary ( HASH in perl )
my %output;     #This is output dictionary after processing all the data to print it out

open(F1,'<',$file1) or die "File not found $file1";
open(F2,'<',$file2) or die "File not found $file2";

#Store both file's contents in %dict1 and %dict2 respectively 
while(<F1>)
{
    my ($key,$value) = split(/\s+/,$_);
    $dict1{$key} = $value;
}

while(<F2>)
{
    my ($key,$value) = split(/\s+/,$_);
    $dict2{$key} = $value;
}

#Get the unique(difference) value from file2 based in the values in file1

foreach my $k ( keys %dict1 )
{
    if ( defined $dict2{$k} )
    {
        my @dict1values=split(";",$dict1{$k});
        my @dict2values=split(";",$dict2{$k});
        foreach (@dict1values)
        {
            if (   $dict2{$k} !~ /[;]*?$_[;]*?/) {

                $output{$k} .=$_.";";

             }
        }
    } else { 
        $output{$k}=$dict1{$k};
    }
}

foreach my $ke (sort(keys(%output)))
{
    print "$ke $output{$ke}\n" if ( defined($output{$ke}) );
}  

Ausgabe :

$ ./testing.pl file1.txt file2.txt 
test1 marco;
test2 zen;liza;
test3 tom;harry;alan
test4 june;

Antwort2

Hier ist einawkVersion, die sehr schnell sein sollte.

Funktioniert mit allem, was dem angeforderten Feldmuster [Zeichenfolge:Schlüssel][Leerzeichen|";"][Zeichenfolge][Leerzeichen|";"] usw. folgt.

$ cat file1;echo "";cat file2
test1 marco;polo;angus
test2 mike;zen;liza
test3 tom;harry;alan
test4 bob;june;janet

test1 polo;angus
test2 mike
test4 bob;janet            
$ awk -F '[ ;]' '
  NR==FNR{ for(i=2;i<=NF;i++){ k[$1,$i]++ } }
  NR!=FNR{ for(i=2;i<=NF;i++){ k[$1,$i]++ } }
  END{ for(i in k){
         if(k[i]==1){
           split(i,arr_i,SUBSEP); 
           k_e[arr_i[1]]=k_e[arr_i[1]]""arr_i[2]";"
         }
       }
       for(i in k_e){
         print i" "k_e[i]
       }
  }' file1 file2 | sort | sed 's/.$//'

test1 marco
test2 liza;zen
test3 harry;alan;tom
test4 june                    

verwandte Informationen