Datei Inhalt sortieren!

L

legeti

Jungspund
Hallo zusammen,

ich habe ein Problem.:think: Ich will den Inhalt einer Textdatei sortieren. Die Datei ist wie folgt aufgebaut.

1. Zeile: ABC1 ABC2 ABC3 ..... (als header, Spaltenzeichnung)
...Zeile: 1 4
3 4
4 3
1 3
3 1
(Trennzeichen nicht Leerzeichen zwischen den Spalten)

Nun sollen doppelte Einträge gelöscht werden. Die Gleichheit hängt von der ersten Spalte ab. Wenn zB. 2 Zeilen mit 1 anfangen, soll nur die weiter unten in der Datei stehende Zeile in der Datei bleiben.

Das Ergebnis des oberen Beispiels wäre also:

ABC1 ABC2
1 3
3 1
4 3

Meine Überlegung ist es den "sort" Befehl zubenutzen. Zusätzlich mit der Option -u (unqi) nun muss aber auch definiert werden das nur nach der ersten Spalte sortiert wird! Wie geht das?? -k1,1 oder wie??? Wahrscheinlich müsste die Liste noch umgedreht werden, da doch sonst der erste Eintrag gelöscht würde oder??

Ich hoffe ihr habt mein Anliegen verstanden:think:

Hoffe auf euer Unterstützung:hilfe2: !

Grüße
Legeti
 
Vielleicht ist meine Denkweise umstaendlich, aber ich wuerde, zum Beispiel mit awk, jeder Zeile (als erste Spalte) ihre Zeilennummer hinzufuegen, dann mit sort nach der zweiten und ersten Zeile sortieren und mit -u jeweils nur die oberste davon ausgeben lassen. Die Zeilennummer bekommst Du dann auch wieder mit awk weg. Hab's nicht ausprobiert, musst wahrscheinlich mit den Optionen ein wenig noch rumspielen.
 
müsste aber doch auch alleine mit der 1. Spalte gehen. Wenn man sie umdreht und sortiert steht die fählt doch die richtige zeile weg? oder?? Aber wie sortiert man nach der ersten Spalte??? Gibt es noch andere Möglichkeiten??

Ich muss beachten, das die Files sehr groß sind und der Server nicht noch mehere Optionen am besten durchführen sollte. Wie am Ende die Zeilen stehen ist egal!
 
Code:
sort -r -k1 dateiname | sort -n -k1 -u
funktioniert bei mir, d.h., mit '-k1' wird nach der ersten Zeile sortiert. '-n' ist wichtig, damit '-u' funktioniert. Der erste Aufruf dreht die Datei um, der 2 laesst nur das (dann) erste Vorkomme jeder 1. Spalte ueber.
 
problem??

HI,

habe das mal eben ausprobiert.

Datei
BAN ID TEST
1 2 2
2 2 2
3 2 3
1 2 1
3 3 3

Das müsste das Ergebnis sein:
BAN ID TEST
1 2 1
2 2 2
3 3 3

Es kommt das aber raus:
BAN ID TEST
1 2 2 <-falsch
2 2 2
3 3 3

Komisch bei der 3 geht es!
Hängt das mit dem Header zusammen??
 
kleines update:

Datei:
1 5 2
2 4 3
3 3 1
4 2 5
5 1 4
1 5 7
2 a 3
1 5 8

Ergebnis: ok!
$ sort -r -k1 test.txt | sort -n -k1 -u
1 5 8
2 a 3
3 3 1
4 2 5
5 1 4

wenn ich in der Datei in der letzten Zeile in der dritten Spalte die 8 durch eine 0 ersetze also:
1 5 2
2 4 3
3 3 1
4 2 5
5 1 4
1 5 7
2 a 3
1 5 0<-

Ergebnis:
$ sort -r -k1 test.txt | sort -n -k1 -u
1 5 7<- falsch!!! es müsste 1 5 0 sein!!
2 a 3
3 3 1
4 2 5
5 1 4

Ich sortiere doch garnicht nach der 3 Spalte!! Warum bringt das sort durcheinander???? Dazu kommt, das auch mal gar kein Wert stehen kann
1 5 2
2 4 3
3 1
4 2 5
5 1
1 5 7
2 3
1 5 0

Hoffe es findet jemand eine Antwort!
 
kleines update:

Datei:
1 5 2
2 4 3
3 3 1
4 2 5
5 1 4
1 5 7
2 a 3
1 5 8

Ergebnis: ok!
$ sort -r -k1 test.txt | sort -n -k1 -u
1 5 8
2 a 3
3 3 1
4 2 5
5 1 4

wenn ich in der Datei in der letzten Zeile in der dritten Spalte die 8 durch eine 0 ersetze also:
1 5 2
2 4 3
3 3 1
4 2 5
5 1 4
1 5 7
2 a 3
1 5 0<-

Ergebnis:
$ sort -r -k1 test.txt | sort -n -k1 -u
1 5 7<- falsch!!! es müsste 1 5 0 sein!!
2 a 3
3 3 1
4 2 5
5 1 4

Ich sortiere doch garnicht nach der 3 Spalte!! Warum bringt das sort durcheinander???? Dazu kommt, das auch mal gar kein Wert stehen kann
1 5 2
2 4 3
3 3
4 2 5
5 1 4
1 5 7
2 a 3
1 5
Ergebnis:
$ sort -r -k1 test.txt | sort -n -k1 -u
1 5 7 <- falsch: richtig wäre: 1 5
2 a 3
3 3
4 2 5
5 1 4


Das Ergebnis ist das ebenfalls falsch!! also 0="" =!=!=:hilfe2:

Hoffe es findet jemand eine Antwort!
 
tac ist das Programm, das ich gesucht und erst nicht gefunden hatte. Es gibt die Datei Zeilenweise vom Ende an wieder. Damit klappten zumindest die Ausnahmefaelle, die Du in Deinem letzten Beitrag erwaehnst:
Code:
tac test.text | sort -u -n -k1
Ich hoffe, damit klapt es. 'sort -r...' war wohl nicht der richtige Ersatz dafuer.
 
Moin,

sieht besser aus. Jetzt besteht wohl das Problem das nach der letzten Zeile ein Zeilenumbruch kommen muss da sonst die Ausgabe so aussieht:

Datei:
1 1 1
2 2 2
3 3 3
1 0 0
1 1 1 <-kein enter

Ausgabe:
$ tac sort.txt | sort -u -n -k1
1 1 11 0 0
2 2 2
3 3 3

Kennst du einen "einfache" Lösung!

Aber schonmal vielen DanK!
 
Tut mir leid, doch bei mir tritt das Problem nicht auf. Was fuer ein System benutzt Du?
Code:
tg@nachtigaller:~$ tac --version
tac (coreutils) 5.2.1
tg@nachtigaller:~$ sort --version
sort (coreutils) 5.2.1
Auf Debian Etch i386
 
Hi,

Code:
$ tac --version
tac (GNU coreutils) 5.97

Code:
$ sort --version
sort (GNU coreutils) 5.97

auf Cygwin 2.510.2.2 (bash)

Es soll hinterher auf einer HP-UX Büchse laufen
 
Hallo
Sorry für den Hinweis: Aber Cygwin ist nicht bash!
Es soll hinterher auf einer HP-UX Büchse laufen
Deshalb solltest du dir für dein Skript eine echte POSIX-conforme Umgebung suchen. Die GNU Utils werden dort wohl auch kaum verfügbar sein.

Einigermaßen portabel wäre es da zum Beispiel gleich Perl zu verwenden.

Gruß Wolfgang
 
HI,

danke für den Hinweis!

Wie würde das den in Perl aussehen??

Gruß
 
was haltet ihr von
sort -u +0 -1
sortiert nur nach dem ersten Feld und bezieht -u auch nur auf dieses. Das natürlich nach dem Umdrehen der Datei. Bei mir macht -k1 nach dem ersten Feld nicht halt. Oder sehe ich da was falsch?
 
Hallo,

würde glaub ich auch funken! aber ich habe kein tac um die Datei umzudrehen!!! Wie kann ich das den ohne tac????

HELP!!!!!
 
Hallo
Wie du tac simulieren kannst habe ich vor einiger Zeit hier geschrieben.
Wenn die Dateien allerdings groß sind, ist das nicht gerade sehr performant und speicherintensiv.
Auch solltest du den Kopf vorher mit sed ausblenden
Code:
sed -e '1d' Datei

Wenn du nur das letzte Vorkommen des ersten Wertes haben willst, empfehle ich wirklich das mit Perl und Hash zu lösen. Dabei den ersten Spaltenwert als Key verwenden und mit der Zeile füllen. Am Ende alles sortiert ausgeben.
Das geht als Einzeiler.
Mit Perl Ausgabe unsortiert:
Code:
perl -anle 'unless(1..1){$h{$F[0]}=$_}END{print $h{$_} for keys %h}' testdatei
Das sollte erträglich sein, wenn die Wertehäufigkeit sich in Grenzen hält.
Hier wird nicht jede Zeile gespeichert, sondern die Werte der ersten Spalte mit nachfolgenden jeweils überschrieben. Auch wird hier gleich die erste Zeile weggelassen und ein vorheriges Umdrehen ist nicht nötig.
Das spart das Sortieren/Umdrehen und sollte auch auf HP-UX laufen!
Wie groß sind denn die Dateien?

Unter Windows Perl musst du die ' durch " ersetzen!

Gruß Wolfgang
 
Hallo,

danke!
Das File ist schon ziemlich groß, es hat ca. 15 Spalten mit Personendaten. z.B Name, Adresse, usw. Da dieses File schon ein gemergtes File ist, hat es auch eine nicht festgelegte Anzahl von Zeilen. Müssten aber schon so ein paar tausende sein. Sollte schon performant sein!!! Darf nicht der Falschenhals sein!!

Was meinst du dazu! Habe dein Perlskript noch nicht getestet! Bleibt die Formatierung erhalten?? Und die anderen Werte in den anderen Spalten bleiben auch erhalten??
 
Hallo
Das sollte schon schnell sein, schließlich ist genau für solche Textbearbeitung ursprünglich Perl erdacht.
Entscheident ist hier in erster Linie die Endgröße der erzeugten Hashtable.
Diese bildet sich (wie ersichtlich) aus der Anzahl der verschiedenen Werte die in der ersten Spalte vorkommen x Zeilenlänge.

Sortieren fällt nicht an. Beim Sortieren steht ja immer das Problem, dass alle Daten vorliegen müssen. Hier nicht nötig, deshalb wird die Datei auch Zeile für Zeile gelesen und nicht am Stück gespeichert.
Ich weiss, es gibt Bubblesort u.a. Vefahren, die aber auch die daten entweder mehrfach lesen müssen, oder im Speicher vorhalten.

Die Formatierung bleibt auch erhalten, allerdings wird auch nichts systemtypisch konvertiert (Windowszeichensatz<->Unixzeichensatz). Aber das ist eine andere Baustelle.

Ich erstelle ein Hashtable mit der ersten Spalte als Key und der Zeile als Inhalt. Da ein vorhandener Key einfach mit neuem Inhalt überschrieben wird, funktioniert das ganze streammäßig wie gefordert. Am Ende steht der Letzte Inhalt im Key - keine Doppelung!
Am Ende wird einfach alles ausgegeben.
Teste es einfach.

Eine 21MB ASCII testdatei geht selbs auf meiner alten Kiste (933 MHZ PIII) noch schnell genug.

$ wc -l testdatei
40000
$ ls -h testdatei
-rw-r--r-- 1 wolle wolle 21M 2006-10-21 20:27 testdatei
$ time perl -anle 'unless(1..1){$h{$F[0]}=$_}END{print $h{$_} for keys %h}' testdatei|wc -l
32768

real 0m7.096s
user 0m4.924s
sys 0m0.128s
Hier waren sogar nur ~ 8000 Werte doppelt.
Gruß Wolfgang
 

Ähnliche Themen

Spalten einer Datei in neue Datei integrieren.

Suche in Datei doppelte Wörter in jeder Zeile bis zum dritten Leerzeichen...

Prblem mit zeilenweises auslesen von Datei und schreiben nach mysql

Tabelle erst ab bestimmter Spalte anzeigen

[gelöst] Sortierung von Zeilen

Zurück
Oben