Ich verwende Solaris 10 und daher funktionieren die grep -Optionen mit -f nicht.
Ich habe zwei durch Pipes getrennte Dateien:
file1:
abc|123|BNY|apple|
cab|234|cyx|orange|
def|kumar|pki|bird|
Datei 2:
abc|123|
kumar|pki|
cab|234
Ich möchte die ersten beiden Spalten von Datei2 mit Datei1 vergleichen (den gesamten Inhalt von Datei1 in den ersten beiden Spalten durchsuchen), wenn sie übereinstimmen, und die übereinstimmende Zeile von Datei1 drucken. Suchen Sie dann nach der zweiten Zeile von Datei 2 und so weiter.
Erwartete Ausgabe:
abc|123|BNY|apple|
cab|234|cyx|orange|
Die Dateien, die ich habe, sind riesig und enthalten ungefähr 400.000 Zeilen. Deshalb möchte ich die Ausführung schnell machen.
shell-script
text-processing
perl
user68365
quelle
quelle
grep
, es ist unter/usr/sfw/bin/ggrep
. stackoverflow.com/questions/15259882/…Antworten:
Dafür wurde awk entwickelt:
Erläuterung
-F'|'
: setzt das Feldtrennzeichen auf|
.NR==FNR
: NR ist die aktuelle Eingabezeilennummer und FNR die Zeilennummer der aktuellen Datei. Die beiden sind nur gleich, während die erste Datei gelesen wird.c[$1$2]++; next
: Wenn dies die erste Datei ist, speichern Sie die ersten beiden Felder imc
Array. Fahren Sie dann mit der nächsten Zeile fort, damit dies nur für die erste Datei gilt.c[$1$2]>0
: Der else-Block wird nur ausgeführt, wenn dies die zweite Datei ist. Wir prüfen daher, ob die Felder 1 und 2 dieser Datei bereits gesehen wurden (c[$1$2]>0
), und drucken die Zeile, wenn dies der Fall war . Inawk
ist die Standardaktion das Drucken der Zeile. Wenn diesc[$1$2]>0
zutrifft, wird die Zeile gedruckt.Alternativ, da Sie mit Perl getaggt haben:
Erläuterung
Die erste Zeile öffnet sich
file2
, liest alles bis zum 2.|
(.+?\|[^|]+
) und speichert das (das$&
ist das Ergebnis des letzten Match-Operators) im%k
Hash.Die zweite Zeile verarbeitet file1 und verwendet denselben regulären Ausdruck, um die ersten beiden Spalten zu extrahieren und die Zeile zu drucken, wenn diese Spalten im
%k
Hash definiert sind .Beide oben genannten Ansätze müssen die 2 ersten Spalten von Datei2 im Speicher halten. Das sollte kein Problem sein, wenn Sie nur ein paar hunderttausend Zeilen haben, aber wenn ja, können Sie so etwas tun
Das wird aber langsamer.
quelle
file2
in den Speicher laden?awk -F'|' 'NR==FNR{c[$1$2]++;next};c[$1$2] > 0'
ist kürzere Version.file2
es doppelte Zeilen?Meiner Ansicht nach
ist was Sie suchen. Es sollte effizient sein, aber ich bin nicht sicher, ob es so genau ist, wie Sie es wollen. Befindet sich
abc|123
(zum Beispiel) in einer Zeile infile1
verschiedenen Spalten, wird diese Zeile ebenfalls gedruckt. Wenn Sie garantieren können, dass dies niemals geschieht, sollte die obige Zeile funktionieren.quelle
Wenn Sie das Problem auf SQL-ähnliche Weise betrachten möchten, sollten Sie auf jeden Fall ein Tool mit dem Namen ' q ' ausprobieren :
Es ist klarer und verständlicher, wenn Sie mit SQL-Abfragen vertraut sind.
quelle
quelle