Grep bewirkt, dass das gesamte System einfriert, während zwei Dateien verglichen werden

461
confetti

Ich wollte zwei Dateien vergleichen und überprüfen, ob jede Zeile in file1existiert file2. Mein erster Versuch: grep -v -f file2 file1. Dies führte zu vielen Syntaxfehlern ( die jedoch nichts eingefroren haben ). Ich fand schnell heraus, es ist, weil ich verwenden müssen, -Fwie erklärt hier . Also lief ich grep -Fvf file2 file2und Sekunden später war mein gesamtes System für Minuten eingefroren, bis xorg gänzlich zusammenbrach.

Ich konnte dieses Bild des eingefrorenen Bildschirms machen: Ressourcenmanager

Und als ich endlich tty2 betreten konnte, wurde ich mit diesem Gruß begrüßt: Fehler

Fragen:

  1. War die Ursache für das eingefrorene System einfach der, dass der RAM ausgeht, oder gibt es mehr?
  2. Warum verwendet grep ~ 14 GB RAM (und möchte mehr), um zwei 250-MB-Dateien zu vergleichen?
  3. Ich könnte Tools verwenden, um den Arbeitsspeicher zu begrenzen, den grep verwenden kann, aber AFAIK alle werden den Prozess beenden, sobald er x GB RAM erreicht hat. Das hilft mir also nicht. Was macht man in einer solchen Situation? Nehmen wir an, wir müssen grep verwenden.

Edit: Ich habe bereits einen Workaround ohne Grep gefunden. Ich bin wirklich neugierig, warum und wie das passieren kann. + 14 GB RAM für zwei 250-MB-Dateien scheint mir einfach ungerade. Ich suche keine Alternative, wie ich meine Dateien mit dieser Frage vergleichen kann.

1
Gibt es einen Grund, warum Sie den Befehl diff nicht verwendet haben? Das scheint ein geeigneteres Werkzeug für diesen Job zu sein. davidgo vor 5 Jahren 0
@davidgo Ich habe diff so ausprobiert: `diff --new-line-format =" "--unchanged-line-format =" "F1 F2", aber es hat nicht funktioniert. Ich habe auch versucht, die Zeilen zu sortieren. Es wurden Tausende von Zeilen gedruckt, die sich in beiden Dateien befinden. Die Sortierung hat es wahrscheinlich verschlimmert, da die Dateien bereits sortiert sind (wie in, sollte der untere Teil von Datei1 mit dem unteren Teil von Datei2 übereinstimmen) und eine Sortierung (alphabetisch) würde es nur verschlimmern. Ich habe das bekommen, was ich wollte, indem ich einfach die ersten ~ 210k Zeilen von file2 abschneide und dann erneut `diff 'verwende, um sicherzustellen, dass der Inhalt genau identisch ist. Ich bin immer noch an Antworten über Grep interessiert, die so viel RAM verwenden. confetti vor 5 Jahren 0
Warum hätten Sie nicht einfach "diff file1 file2" verwendet? (--new-line-format und --unchanged-line-format sind in meiner Version von diff noch nicht einmal vorhanden) davidgo vor 5 Jahren 0
@davidgo Denn das würde mir alle Unterschiede zeigen, wenn ich nur wissen möchte, ob jede Zeile in file1 auch in file2 existiert. Die + 200.000 Zeilen in Datei2, die sich nicht in Datei1 befinden, würden die Ausgabe überfluten. Ich habe meine Frage klarer formuliert. Ich habe wirklich mehr nach einer Erklärung für das Verhalten von grep als nach einer Alternative für die Operation. confetti vor 5 Jahren 0

1 Antwort auf die Frage

6
dirkt
  1. Der Grund war definitiv der Speicher.

  2. Weil Sie nicht „ den Vergleich von zwei Dateien“, die Sie verwenden eine 250MB - Datei als Quelle von Mustern für grep. Grep kompiliert diese Muster in eine Variante eines deterministischen endlichen Automaten, und die Darstellung dieser DFAs belegt den Speicher. Wenn Sie viele Muster haben (z. B. 250 MB Muster), nimmt dies viel Platz in Anspruch, da die Umwandlung des nichtdeterministischen endlichen Automaten, der vielen Mustern entspricht, in einen DFA zu exponentiellem Aufblasen führen kann.

grepkann sehr wenige Muster in einer oder mehreren großen Dateien suchen. Es ist nicht zum "Vergleichen" von Dateien gedacht. Wenn Sie versuchen, es dafür zu verwenden, können Dinge schief gehen. Wie in Ihrem Fall.

Komplexität ist wichtig, deshalb lernst du O-Notation und all das ausgefallene Zeug.

  1. In einer solchen Situation verwenden Sie ein Programm, das auf Ihre Situation zugeschnitten ist, nicht ein Programm, das einen Algorithmus verwendet, der für Ihre Art von Problem raumexponentiell ist.

Sie sagten, Sie wollten die Alternative nicht wissen, aber da es sich um ein weniger bekanntes Werkzeug handelt, sage ich es Ihnen trotzdem:

Wenn die Frage "Ist jede Zeile von Datei1 auch unabhängig von der Reihenfolge in Datei2 vorhanden" vorhanden ist, müssen Sie beide Dateien sortieren. Anschließend verwenden Sie comm, was sortierte Dateien erwartet, und gibt (1) Zeilen in Datei1 aus Nicht in Datei2, (2) Zeilen in Datei2, sondern nicht in Datei1 und (3) Zeilen in beiden Dateien, je nach Belieben.

Genau das, was ich in einer Antwort gesucht habe, vielen Dank für die großartige Erklärung. confetti vor 5 Jahren 0