[root@server]# awk '!seen[$0]++' out.txt > cleaned
awk: (FILENAME=out.txt FNR=8547098) fatal error: internal error
Aborted
[root@server]#
Der "" Server "" verfügt über: 8 GByte RAM + 16 GByte SWAP, x> 300 GByte freien Speicherplatz, amd64, Desktop-CPU. Wissenschaftliches Linux 6.6. Nichts anderes läuft darauf, um LOAD zu machen. Awk bricht nach ein paar Sekunden ab. Out.txt ist ~ 1.6 GByte. GNU Awk 3.1.7.
Frage : Wie kann ich die doppelten Zeilen entfernen, während die Reihenfolge der Zeilen beibehalten wird? Groß- / Kleinschreibung ist auch wichtig, zB: "A" und "a" sind zwei verschiedene Zeilen, müssen es behalten. "A" und "a" sind jedoch doppelt vorhanden, nur das erste wird benötigt.
Antwort könnte in irgendetwas sein .. wenn awk nicht gut dafür ist .. dann perl / sed .. was könnte das Problem sein?
[root@server]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 61945
max locked memory (kbytes, -l) 99999999
max memory size (kbytes, -m) unlimited
open files (-n) 999999
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 99999999
cpu time (seconds, -t) unlimited
max user processes (-u) 61945
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
[root@server]#
Update: Ich habe es auf einem RHEL-Rechner versucht, es wird nicht abgebrochen, aber ich hatte keine Zeit, bis es fertig ist. Warum unterscheidet sich SL Linux nicht von RHEL?
Update: Ich versuche es mit einer virtuellen Ubuntu 14-Version. Soweit funktioniert es! Es ist kein Ulimit-Problem: mawk 1.3.3
root@asdf-VirtualBox:~# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 51331
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 51331
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
root@asdf-VirtualBox:~#
quelle
awk
Versionen in zwei Maschinen?out.txt
? Funktioniert derselbe Befehl, wenn Sie es mit einer kleineren Datei versuchen? Wie viele Benutzer auf dem Computer? War genügend Speicher für den Prozess verfügbar? Gibt es etwas Besonderes in Zeile 8547098 der Eingabedatei?Antworten:
Ich bezweifle, dass dies einen Unterschied bewirken wird, aber für den Fall, dass dies in Perl nicht anders ist:
Wenn das Problem darin besteht, die eindeutigen Zeilen im Speicher zu behalten, tritt das gleiche Problem auf wie bei dem
awk
Versuch. Ein anderer Ansatz könnte also sein:Wie es funktioniert:
In einem GNU-System
cat -n
wird jeder Zeile die Zeilennummer vorangestellt, gefolgt von einer gewissen Anzahl von Leerzeichen und einem <tab> -Zeichen.cat
leitet diese Eingabedarstellung ansort
.sort
Mit der-k2
Option wird festgelegt, dass beim Sortieren nur die Zeichen vom zweiten Feld bis zum Ende der Zeile berücksichtigt und diesort
Felder standardmäßig nach Leerzeichen (odercat
den eingefügten Leerzeichen und dem <Tabulator> ) aufgeteilt werden .Wenn gefolgt
-k1n
, wird zuerstsort
das 2. Feld und dann - bei identischen-k2
Feldern - das 1. Feld als numerisch sortiert betrachtet. Wiederholte Zeilen werden also in der Reihenfolge sortiert, in der sie erscheinen.uniq
- wobei angegeben wird, dass das erste Feld ignoriert werden soll (-f1
- und auch durch Leerzeichen getrennt) - und was zu einer Liste eindeutiger Zeilen in der Originaldatei führt und an zurückgeleitet wirdsort
.sort
das erste Feld (cat
die eingefügte Zeilennummer) numerisch sortiert, wobei die Sortierreihenfolge auf den Wert in der Originaldatei zurückgesetzt und die Ergebnisse weitergeleitet werdencut
.cut
die Zeilennummern, die von eingefügt wurdencat
. Dies geschieht, indemcut
nur vom 2. Feld bis zum Ende der Zeile gedruckt wird (undcut
das Standardtrennzeichen ist ein <tab> -Zeichen) .Um zu veranschaulichen:
quelle
sort
! Aber die meistensort
könnenuniq
von selbst, so dass Sie Ihr Skriptsort -uk2 | sort -bk1,1n
sort
? Ich dachte,-u
es wäre ein GNU-Feature.-u
angeben, dass das 1. Feld ignoriert werden soll? Nachman sort
der-u
nicht eine der möglichen Optionen für die-f
, so dass ich es nicht denken kann hier verwendet werden.EDIT 1: Funktioniert es wirklich? (im Vergleich)
Fall 1 : 100_000_000 Zufallszahlen (jeweils 5 Stellen), 566 MByte, 31_212 verschiedene Werte:
Fall 2 : 50_000_000 Rand-Nummern (je 10 Stellen), 516 MByte, 48_351_464 verschiedene Werte:
(Die folgenden Zahlen sind nicht sehr genau):
Sol2 mit Cache ist:
Sortieren kann auch optimiert werden, indem eine Option für die Cachegröße hinzugefügt wird (wird nicht ausgeführt).
Eine kurze Schlussfolgerung:
sort
ist ein fantastischer Befehl!quelle
sort -uk2
undsort -nk1,1
sind anders. Der erste berücksichtigt von der 2cd-Taste bis zum Zeilenende, der zweite nur die erste Taste. Sie sollten Ihrsort -nk1
dort ändern - es könnte sogar schneller sein, aber es wird definitiv zuverlässiger sein. Übrigens - das sind ein paar hübsche Kisten.cat -n
so ein Vorsprung ? Ich weiß nicht, wie dieser Befehl funktioniert.cat -n
von jedemline
inspaces + the number + \t + line
- das ideale Format zum Sortieren und SchneidenIch habe benutzt
BINMODE = rw: um Zeilenende-Abschlusszeichen zufrieden zu stellen. (Ich lebe in einer gemischten Umgebung)
Logik ist einfach.
Wenn sich die aktuelle Zeile nicht im assoziativen Array befindet, fügen Sie sie dem assoziativen Array hinzu und drucken Sie sie zur Ausgabe aus.
Bei diesem Ansatz kann es zu Speicherbeschränkungen kommen. Bei sehr großen Dateien und Dateigruppen habe ich Variationen verwendet und den Dateispeicher verwendet, um die Einschränkungen zu umgehen.
quelle
Die ordnungserhaltende Semantik Ihres Problems hat eine wunderbare Eigenschaft: Sie können das Problem unterteilen. Sie können
split -l 1000000
die Eingabedatei bearbeiten. Die 1000000-Linien, die es produziert, haben lexikalisch geordnete Namen, was gut ist. dann vereinheitliche die Stücke; und dann (als zweiter Durchgang) vereinheitlichen Sie die Ausgaben von diesen.Dies löst das Speichermangelproblem (durch Begrenzen des Speicherbedarfs) auf Kosten der Umwandlung in eine Multipass-Lösung.
Speziell:
Eingabedaten generieren:
Teilen Sie die Eingabedaten auf:
Führen Sie den Uniqifier auf einmal aus (behält alle eindeutigen Eingabezeilen im Speicher bei):
Führen Sie den Uniqifier bei geteilten Teilen aus (behält nur eindeutige Eingabezeilen von jedem Teil im Speicher bei) und reduzieren Sie ihn dann als zweiten Durchgang:
Vergleichen Sie:
Ich kenne das Verhältnis von eindeutigen zu nicht eindeutigen Zeilen in Ihrer Eingabe nicht und weiß auch nicht, wie gut die Eingabezeilen gemischt sind. Daher gibt es einige Optimierungen in Bezug auf die Anzahl der benötigten aufgeteilten Dateien.
quelle
Ein anderer Ansatz (der als separate Antwort veröffentlicht werden sollte) ist: Anstelle des Split-File-Ansatzes, bei dem temporäre Dateien erstellt werden, führen Sie die Stapelverarbeitung in der Uniqifier-Software selbst durch. Beispiel: Verwenden einer Ruby-Uniqifier-Implementierung zu Erläuterungszwecken:
Die Idee ist, das Hash-Set von Zeit zu Zeit zu löschen. Dann wird dies iterativ:
Sie können diese begrenzte Version also so oft ausführen, bis sich die Zeilenanzahl von einer Iteration zur nächsten nicht mehr ändert.
Beachten Sie, dass diese capped-uniqm-Technik sprachunabhängig ist: Sie können das
lines_seen
Array alle N Zeilen löschen, unabhängig davon , ob Sie awk, Python, Perl, C ++ usw. verwenden. Für alle diese Sprachen gibt es set-clear-Methoden. Ich glaubeawk
, esdelete
ist nicht Standard, aber üblich.quelle