Finden Sie Übereinstimmungen für die 5. Spalte in einer Pipe-Delim-Datei

Finden Sie Übereinstimmungen für die 5. Spalte in einer Pipe-Delim-Datei
File 1:
Connect|20130320000023|UTC|PPP|[email protected]|[email protected]|0BCBE578|
File 2:
Connect|20130320000023|UTC|PPP|[email protected]|[email protected]|0BCBE578|
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

Ich muss in Spalte 5 sowohl in Datei 1 als auch in Datei 2 übereinstimmende Datensätze finden. Aus dem obigen muss ich also Folgendes in der Ausgabe zurückgeben:

Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

Vielen Dank,

Antwort1

Methode Nr. 1: grep & awk

Sie können hierfür diesen Code-Schnipsel verwenden:

$ grep -f <(awk -F '|' '{print $5}' file1)  file2
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

Einzelheiten

Das verwendete Bit awkanalysiert die erste Datei und file1extrahiert alle 5. Spalten. Diese Werte werden dann als Liste verwendet grep, die alle Zeilen in der 2. Datei druckt, die eine Übereinstimmung enthalten.

Einschränkungen bei dieser Methode

Diese Methode gleicht jedes Vorkommen der 5. Spalte von file1in ab file2.

Methode Nr. 2: Einfach awk

Ein anderer Ansatz, der in der Vergangenheit auf der Site verwendet wurde, ist die Verwendung awkder FNR-Funktion. Dabei awkwerden zwei Dateien durchlaufen, wobei die zweite Datei Zeile für Zeile durchgegangen wird, für jede Zeile in der ersten.

Ein Ansatz wie dieser würde es schaffen. Schreiben Sie das Folgende in eine Datei cmds.awk:

FNR == NR {
f1[$5] = $5
next
}

{ if ($5 == f1[$5]) print $0; }

Sie können dies dann wie folgt ausführen:

$ awk -F '|' -f cmds.awk file1 file2

NOTIZ:Sie hätten awkstattdessen dieses Muster verwenden können:

FNR == NR {
f1[$5] = $5
next
}

{ if ($5 in f1) print $0; }

Beispiel

$ awk -F '|' -f s.awk file1 file2
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

Einschränkungen bei dieser Methode

Dieser Ansatz kann nur eine einzelne Instanz jeder E-Mail-Adresse von verarbeiten file1. Wenn es also zwei Zeilen gibt, die beide den gleichen Wert für die 5. Spalte haben, kann nicht zwischen ihnen unterschieden werden. Dies scheint jedoch angesichts Ihrer Anforderungen im OP akzeptabel.

Zusammenführen und Sortieren

Sie können dies auch mit joinund tun sort.

$ join -t '|' -j 5  <(sort -k5,5 file2) <(sort -k5,5 file1) | sed 's/||.*//'

Dadurch wird der Trenner verwendet |und die sortierten Dateien werden in der 5. Spalte zusammengeführt. Bei diesem Ansatz werden die Übereinstimmungen sowohl von file1als auch gedruckt file2, sodass wir seddie 2. Übereinstimmung am Ende abschneiden.

Beispiel

$ join -t '|' -j 5  <(sort -k5,5 file2) <(sort -k5,5 file1) | sed 's/||.*//'
[email protected]|Connect|20130320000025|UTC|PPP|[email protected]|0BCBE578

Antwort2

Ich würde das Ganze in Perl machen:

$ perl -F'\|' -ane '$k{$F[4]}++; print if $k{$F[4]}>1' file1 file2  
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|
  • -aaktiviert die automatische Feldaufteilung im Array @F.
  • -F'\|'setzt das Feldtrennzeichen für -aauf |.
  • Speichern Sie für jede verarbeitete Zeile das 5. Feld (Array-Indizes beginnen in 0Perl bei ) als Hash-Schlüssel ( $k{$F[4]}++und erhöhen Sie seinen Wert um eins. Beim zweiten Mal, wenn ein Feld angezeigt wird, ist dieser Wert 2.
  • Das Skript verarbeitet jede Zeile beider Dateien ( file1vorher file2) und druckt die Zeile, wenn das 5. Feld zuvor gesehen wurde, d. h. wenn $k{$F[4]}es größer als eins ist.

Dies setzt voraus, dass keine fünfte Spalte innerhalb derDasselbeDatei. Wenn dies nicht der Fall ist und einige Spalten in derselben Datei dupliziert werden können, verwenden Sie stattdessen Folgendes:

perl -e 'open(A,"$ARGV[0]"); while(<A>){@F=split(/\|/);$k{$F[4]}++;}
         open(B,"$ARGV[1]"); while(<B>){@F=split(/\|/); print if $k{$F[4]} 
         }' file1 file2 

Antwort3

Wenn die Dateigrößen vergleichbar sind, ist die optimale Lösungsortbeide Dateien nach der Spalte, die Sie interessiert, und dannjoinsie durch diese Spalte. Wenn die Dateigrößen Nund sind, Mdann ist die asymptotische Laufzeit O(N*log(N)+M*log(M)).

Wenn eine der Dateien viel, viel kleiner ist als die andere, O(N*M)ist die Lösung in den anderen Antworten besser.

verwandte Informationen