Ich habe eine Datei mit ungefähr 10 Millionen Zeilen.
Ich möchte alle Zeilen in der Datei entfernen, die weniger als sechs Zeichen enthalten.
Wie mache ich das?
command-line
text-processing
Sag mir warum
quelle
quelle
Antworten:
Dafür gibt es viele Möglichkeiten.
Verwenden von
grep
:Jetzt
out.txt
enthält Zeilen mit sechs oder mehr Zeichen.Umgekehrter Weg:
Verwenden
sed
, Entfernen von Zeilen mit einer Länge von 5 oder weniger:In umgekehrter Reihenfolge werden Zeilen mit einer Länge von sechs oder mehr gedruckt:
Sie können die Ausgabe in einer anderen Datei mit dem
>
Operator "like"grep
speichern oder die Datei direkt bearbeiten, indem Sie folgende-i
Optionen verwendensed
:Die Originaldatei wird wie folgt gesichert:
file.txt.bak
Die geänderte Datei wird gesichertfile.txt
.Wenn Sie keine Sicherungskopie erstellen möchten:
Verwenden Sie die Shell, Langsamer, Tun Sie dies nicht , um eine andere Methode zu zeigen:
Unter Verwendung
python
, sogar langsamer alsgrep
,sed
:Verwenden Sie das Listenverständnis besser, um pythonischer zu sein:
quelle
Es ist sehr einfach:
Dies ist äußerst effizient, da
grep
nicht versucht wird, mehr als erforderlich zu analysieren oder die Zeichen in irgendeiner Weise zu interpretieren: Es wird einfach eine (vollständige) Zeile an stdout gesendet (die die Shell dann an resultfile weiterleitet) , sobald 6 angezeigt wird Zeichen in dieser Zeile (entspricht.
in einem regulären Ausdruck einem beliebigen Zeichen).Grep gibt also nur Zeilen mit 6 (oder mehr) Zeichen aus, und die anderen werden nicht von grep ausgegeben, damit sie nicht in die Ergebnisdatei gelangen.
quelle
Lösung 1: Verwenden von C
Schnellster Weg: Kompilieren und starten Sie dieses C-Programm:
Kompilieren Sie mit
gcc program.c -o program
, führen Sie mit aus./program file line_length
(wobeifile
= Pfad zur Datei undline_length
= minimale Zeilenlänge in Ihrem Fall6
; die maximale Zeilenlänge ist auf1000000
Zeichen pro Zeile begrenzt; Sie können dies ändern, indem Sie den Wert von ändernMAX_BUFFER_SIZE
).(Trick zum Ersetzen
\n
mit hier\0
gefunden .)Vergleich mit allen anderen Lösungen, die für diese Frage vorgeschlagen wurden, mit Ausnahme der Shell-Lösung (Testlauf mit einer ~ 91-MB-Datei mit 10-MB-Zeilen und einer durchschnittlichen Länge von 8 Zeichen):
Lösung 2: Verwenden von AWK:
length>=6
:length>=6
Gibt TRUE zurück, wird der aktuelle Datensatz gedruckt.Lösung 3: Verwenden von Perl:
lenght>=6
TRUE zurückgegeben wird, wird der aktuelle Datensatz gedruckt.quelle
awk
Lösung gewartet ...sed
Lösung löschen (es passiert, ich weiß). XDpos
Variablen? Ich bekomme es einen Zeiger auf das Zeichen inline
mit einem Newline-Zeichen zurück, aber Sie scheinen es nie zu verwenden. Und wenn Sie es nicht finden, setzen Sie es einfach gleich\0
.\0
(strchr()
gibt einen NULL-Zeiger zurück, wenn das Zeichen nicht gefunden wird). Es geht darum, jede neue Zeile am Ende jeder Zeile durch eine neue zu ersetzen,\0
damit die neue Zeile niemals gezählt wirdstrlen()
. Dies bedeutet, dass die Länge immer mit 6 verglichen werden kann, unabhängig davon, ob in der letzten Zeile möglicherweise eine neue Zeile fehlt. Ich weiß, dass es viel effizienter ist, nur die letzte Zeile anders zu behandeln. Ich werde das wahrscheinlich später aktualisieren.grep
Lösung für dieselbe Datei getestet und sie ist tatsächlich schneller (wahrscheinlich, weil diesstrlen()
hier nicht die beste Idee ist). . Ich werde versuchen, einegetchar()
Schleife zu verwenden, um stattdessen nur das erste N-Zeichen zu überprüfen. Ich denke, das sollte es sichtbar verbessern. Und ja, jede Linie über die Länge des Puffers wird einfach auf die Länge des Puffers zugeschnitten.Sie können Vim im Ex-Modus verwenden:
\v
schalte die Magie ein.{6}
Finde Zeilen mit 6 oder mehr Zeichenv
Auswahl umkehrend
löschenx
speichern und schließenquelle
Ruby-Lösung:
Einfache Idee: Leiten Sie die Datei in Rubys Standard um und drucken Sie die Zeile nur dann aus dem Standard, wenn die Länge größer oder gleich 6 ist
quelle