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 awk
analysiert die erste Datei und file1
extrahiert 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 file1
in ab file2
.
Methode Nr. 2: Einfach awk
Ein anderer Ansatz, der in der Vergangenheit auf der Site verwendet wurde, ist die Verwendung awk
der FNR-Funktion. Dabei awk
werden 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 awk
stattdessen 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 join
und 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 file1
als auch gedruckt file2
, sodass wir sed
die 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|
-a
aktiviert die automatische Feldaufteilung im Array@F
.-F'\|'
setzt das Feldtrennzeichen für-a
auf|
.- Speichern Sie für jede verarbeitete Zeile das 5. Feld (Array-Indizes beginnen in
0
Perl 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 (
file1
vorherfile2
) 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ösungsort
beide Dateien nach der Spalte, die Sie interessiert, und dannjoin
sie durch diese Spalte. Wenn die Dateigrößen N
und sind, M
dann 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.