Sortieren von Spalten

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
tuxfreund
Beiträge: 58
Registriert: 01.12.2009 19:19:46

Sortieren von Spalten

Beitrag von tuxfreund » 01.12.2009 20:29:45

Hallo

Ich habe eine CSV Datei deren Datensätze durch Semikolon getrennt sind. In einer Zeile befinden sich dadurch 13 Felder. Zeilenanzahl ca 4000. Nun wollte ich die Zeilen an Hand der 3.Spalte sortieren (alle Werte sind ganze Zahlen):
sort -t ';' +3 ./spiele.csv. Fehlermeldung: sort: Öffnen fehlgeschlagen: +3: Datei oder Verzeichnis nicht gefunden. Was kann ich tun? In man sort finde ich diese Syntax zwar nicht, solche Beispiele sind aber auf einigen Internetseiten oft erwähnt worden.

Jetzt möchte ich noch das gewünschte Sortiersystem erläutern. Betrachten wir mal die Spalte 3 aller Zeilen, so ist das ein ziemliches Durcheinander. Aber diese Reihenfolge darf nicht zerstört werden! Es sollen lediglich alle mehrfach vorkommenden Zahlen zusammensortiert werden.
Beispiel
original: sortiert:
72.............72
8................8
1................8
8................1
4................1
1................4
55..............4
4................4
4...............55

Danke im Voraus

chrisbra
Beiträge: 122
Registriert: 19.10.2005 09:36:09
Wohnort: Sachsen-Anhalt
Kontaktdaten:

Re: Sortieren von Spalten

Beitrag von chrisbra » 01.12.2009 21:24:33

tuxfreund hat geschrieben:Hallo

Ich habe eine CSV Datei deren Datensätze durch Semikolon getrennt sind. In einer Zeile befinden sich dadurch 13 Felder. Zeilenanzahl ca 4000. Nun wollte ich die Zeilen an Hand der 3.Spalte sortieren (alle Werte sind ganze Zahlen):
sort -t ';' +3 ./spiele.csv. Fehlermeldung: sort: Öffnen fehlgeschlagen: +3: Datei oder Verzeichnis nicht gefunden. Was kann ich tun? In man sort finde ich diese Syntax zwar nicht, solche Beispiele sind aber auf einigen Internetseiten oft erwähnt worden.

Jetzt möchte ich noch das gewünschte Sortiersystem erläutern. Betrachten wir mal die Spalte 3 aller Zeilen, so ist das ein ziemliches Durcheinander. Aber diese Reihenfolge darf nicht zerstört werden! Es sollen lediglich alle mehrfach vorkommenden Zahlen zusammensortiert werden.
Beispiel
original: sortiert:
72.............72
8................8
1................8
8................1
4................1
1................4
55..............4
4................4
4...............55

Danke im Voraus
Das wird mit sort nichts, weil Deine Sortierreihenfolge eigenwillig ist.

Ich wollte ja schon immer mal was mit awk machen, hier ist meine Lösung, wenn ich alles richtig verstanden habe :? :

Code: Alles auswählen

awk -F';' '{a[$3]= $3 in a ? a[$3] ORS $0 : $0;} END {asorti(a,b); for (i in b) { print a[b[i]]} }' cols.txt
Ach ja, bei deinem sort-Aufruf gibst du das gewünschte Feld mit -k an
Meine Whishlist
:wq!

Benutzeravatar
Meillo
Moderator
Beiträge: 9254
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Sortieren von Spalten

Beitrag von Meillo » 02.12.2009 16:37:31

tuxfreund hat geschrieben:Nun wollte ich die Zeilen an Hand der 3.Spalte sortieren [...]

Es sollen lediglich alle mehrfach vorkommenden Zahlen zusammensortiert werden.
Ich würde das eher als ``gruppieren'' bezeichnen, da ja überhaupt nichts sortiert wird.

chrisbra hat geschrieben:

Code: Alles auswählen

awk -F';' '
{
  a[$3]= ($3 in a) ? a[$3] ORS $0 : $0;
}

END {
  asorti(a,b);
  for (i in b) {
    print a[b[i]]
  }
}
' cols.txt
(Ich habe mir erlaubt deine Zeile zu formatieren und Klammern bei ?: einzufügen.)

Anmerkungen:
- asorti() (und asort()) sind Erweiterungen von gawk, also nicht überall zu finden.
- sortiert werden sollte nicht (zudem: asorti() sortiert auf den Indizes -- das sind immer Strings -- somit kommt 100 vor 4).
- for (i in b) ... gibt die Elemente *nicht* sortiert aus, da Arrays immer assoziativ sind (Hash-Tables) und damit keine Reihenfolge haben.

Für dein erstes awk-Programm ist das aber gar nicht schlecht, und dass du solche Feinheiten nicht weißt, ist nur verständlich.

Meine Version ist zum größten Teil gleich wie dein Ansatz. Ich habe eigentlich nur das Array `keys' eingeführt, das die einzelnen Werte der Spalte nach der sortiert werden soll, geordnet ablegt. Am Ende wird in dieser Reihenfolge ausgegeben.

Code: Alles auswählen

awk -F; '{
        if (a[$3] == "") {
                keys[nkey++] = $3;
                a[$3] = $0;
        } else {
                a[$3] = a[$3] ORS $0;
        }
}

END {
        for (i=0; i<nkey; i++) {
                print a[keys[i]];
        }
}'

(btw @chrisbra: Bitte keine Fullquotes. Entweder gezielt zitieren oder gar nicht.)
Use ed once in a while!

tuxfreund
Beiträge: 58
Registriert: 01.12.2009 19:19:46

Re: Sortieren von Spalten

Beitrag von tuxfreund » 02.12.2009 18:06:14

Hallo,
erst mal vielen Dank an alle für die Mühe. Wie ich sehe, wurde das Problem richtig verstanden. "Zeilen anordnen, an Hand von Spalteneinträgen, die wegen mehrfachem Auftreten gruppiert werden müssen. Aber in Reihenfolge des Originals von oben nach unten." Allerdings muss ich noch was wichtiges ergänzen: Sollte der Wert Null sein, dann nicht die Nullen gruppieren. Es geht weiter mit nächster Zeile. Ich bin kein Linux-Anfänger, aber ein Shell-Lehrling. In meinem Shell-Buch bin ich noch nicht bei awk gelandet. Deshalb meine Frage zum Kopf unseres Sortierscripts, das ja später über die Konsole aufgerufen wird: #!/bin/bash oder #!/usr/bin/gawk -f
Bin gespannt auf weitere Vorschläge. Danke

chrisbra
Beiträge: 122
Registriert: 19.10.2005 09:36:09
Wohnort: Sachsen-Anhalt
Kontaktdaten:

Re: Sortieren von Spalten

Beitrag von chrisbra » 02.12.2009 21:52:38

Meillo hat geschrieben:Anmerkungen:
- asorti() (und asort()) sind Erweiterungen von gawk, also nicht überall zu finden.
Richtig. Aber im Debianforum ging ich von gawk mal aus ;)
Meillo hat geschrieben: - sortiert werden sollte nicht (zudem: asorti() sortiert auf den Indizes -- das sind immer Strings -- somit kommt 100 vor 4).
- for (i in b) ... gibt die Elemente *nicht* sortiert aus, da Arrays immer assoziativ sind (Hash-Tables) und damit keine Reihenfolge haben.
Hm, da hab ich irgendwas flasch verstanden. Aber zumindest das Beispiel hat bei mir funktioniert ;) (zufällig ....)
Meillo hat geschrieben:

Code: Alles auswählen

awk -F; '{
        if (a[$3] == "") {
                keys[nkey++] = $3;
                a[$3] = $0;
        } else {
                a[$3] = a[$3] ORS $0;
        }
}

END {
        for (i=0; i<nkey; i++) {
                print a[keys[i]];
        }
}'
Ok. Geht auch.
Meillo hat geschrieben: (btw @chrisbra: Bitte keine Fullquotes. Entweder gezielt zitieren oder gar nicht.)
Ja, wenn man denn in so einem Forum vernünftig quoten könnte. Aber man bricht sich ja in den Text-Boxen die Finger, beim ständig
blah hat geschrieben: schreiben.

Mist, ich bin einfach zu alt für so neumodischen Web-Kram. Usenet und Mail liegen mir besser.

@tuxfreund: Füge am Anfang noch ein:
$3!=0 {a[$3]=....
Meine Whishlist
:wq!

tuxfreund
Beiträge: 58
Registriert: 01.12.2009 19:19:46

Re: Sortieren von Spalten

Beitrag von tuxfreund » 02.12.2009 23:07:19

Solange chrisbra mit meillo schreibt, ist mir ja nicht geholfen. Meine Frage:
Deshalb meine Frage zum Kopf unseres Sortierscripts, das ja später über die Konsole aufgerufen wird: #!/bin/bash oder #!/usr/bin/gawk -f
. Bei aller Achtung: Vielleicht sind die scripts ja richtig, aber ich bin zu blöde die einzugeben? Denn bis jetzt bekomme ich diverse Fehlermeldungen, obwohl ich gawk installiert habe.

tuxfreund
Beiträge: 58
Registriert: 01.12.2009 19:19:46

Re: Sortieren von Spalten

Beitrag von tuxfreund » 03.12.2009 10:10:54

Guten Morgen
Also Script läuft...überprüfe gerade, die Ergebnisse
Danke

Benutzeravatar
Meillo
Moderator
Beiträge: 9254
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Sortieren von Spalten

Beitrag von Meillo » 03.12.2009 12:04:52

chrisbra hat geschrieben:Ja, wenn man denn in so einem Forum vernünftig quoten könnte. Aber man bricht sich ja in den Text-Boxen die Finger, beim ständig
blah hat geschrieben: schreiben.
Ich füge nur beim ersten Zitat den Namen ein (wird automatisch gemacht wenn man mit ``zitieren'' antwortet). Bei weiteren Zitatteilen des gleichen Autors lasse ich den Namen weg.

Du kannst ja auch gleich deine Antwort schreiben. Falls keine anderen Posts dazwischen liegen, sieht man den Zusammenhang ja. (Das ist anders als bei Mails die lauter einzelne Dokumente sind.)


@tuxfreund: Sieht so aus als habe sich deine Frage schon erledigt.

Es kommt halt darauf an was du willst. Du kannst den awk-Aufruf in ein Shellscript packen (#!/bin/sh) oder du erstellst ein ausführbares awk-Script (#!/usr/bin/awk -f). Beides ist möglich. (Ersteres ist meist geschickter.)
Use ed once in a while!

tuxfreund
Beiträge: 58
Registriert: 01.12.2009 19:19:46

Re: Sortieren von Spalten

Beitrag von tuxfreund » 03.12.2009 15:46:16

Hallo
Direkt im shellscript starten geht nicht. Direkt in die Konsole kopieren geht erst recht nicht. Es geht nur über eine awk -f Konstruktion, wobei man die Hochkommas weglassen muss. Auch klappte die Figur -F; nicht. Muss ein -F";" sein. Wo genau muss jetzt die Anweisung für die Nullwerte hin?
Gruss

Benutzeravatar
Meillo
Moderator
Beiträge: 9254
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Sortieren von Spalten

Beitrag von Meillo » 03.12.2009 18:10:37

tuxfreund hat geschrieben:Direkt im shellscript starten geht nicht.
So sollte das klappen:

Code: Alles auswählen

#!/bin/sh
# file: grouping.sh

awk -F';' '
$3 != 0 {
        if (a[$3] == "") {
                keys[nkey++] = $3;
                a[$3] = $0;
        } else {
                a[$3] = a[$3] ORS $0;
        }
}

END {
        for (i=0; i<nkey; i++) {
                print a[keys[i]];
        }
}' "$1"

Code: Alles auswählen

./grouping.sh file-with-data
Es geht nur über eine awk -f Konstruktion, wobei man die Hochkommas weglassen muss.
Nach -f übergibt man den Namen eines awk-Scriptfiles. Oder ohne -f und das Programm direkt auf der Kommandozeile (dann entspechend gequotet).
Auch klappte die Figur -F; nicht. Muss ein -F";" sein.
Das ist korrekt. Ich hatte zum Testen den Doppelpunkt als Trenner, und habe erst beim Posten ins Forum ersetzt. Deshalb ist mir das nicht aufgefallen.
Wo genau muss jetzt die Anweisung für die Nullwerte hin?
Siehe Code in diesem Post.
Use ed once in a while!

chrisbra
Beiträge: 122
Registriert: 19.10.2005 09:36:09
Wohnort: Sachsen-Anhalt
Kontaktdaten:

Re: Sortieren von Spalten

Beitrag von chrisbra » 03.12.2009 19:37:51

tuxfreund hat geschrieben:Hallo
Direkt im shellscript starten geht nicht. Direkt in die Konsole kopieren geht erst recht nicht. Es geht nur über eine awk -f Konstruktion, wobei man die Hochkommas weglassen muss. Auch klappte die Figur -F; nicht. Muss ein -F";" sein.
Gruss
Der Semikolon muß in Hochkommas gesetzt werden, weil sonst die Shell das Semikolon sehen würde und es nicht als Argument an AWK durchreichen würde. (; heißt Vorheriges Command ist zu Ende, danach folgt der nächste Befehl).

Das stand übrigens so auch meinem Aufruf, den ich angegeben hatte ;)

Alternativ kannst Du in einem awk-Script im Begin-Block den Field Separator angeben.

Du nimmst halt Meillos Script (meins nicht, das ist kaputt):

Code: Alles auswählen

#!/usr/bin/gawk -f
BEGIN {FS=";"}
$3 != 0{
        if (a[$3] == "") {
                keys[nkey++] = $3;
                a[$3] = $0;
        } else {
                a[$3] = a[$3] ORS $0;
        }
}

END {
        for (i=0; i<nkey; i++) {
                print a[keys[i]];
        }
}
Und rufst dann das Script auf (nicht vergessen, ausführbar machen): ./awk_script.awk datei.txt
Wo genau muss jetzt die Anweisung für die Nullwerte hin?
Was genau soll denn passieren, wenn in Spalte 3 eine Null auftaucht? Soll diese Zeile rausgefiltert werden? oder soll die Zeile ganz einfach so wie sie ist ausgegeben werden?
Das Script oben macht ersteres, für zweiteres müßte man das Script noch anpassen.

ciao,
Christian
Meine Whishlist
:wq!

Benutzeravatar
Meillo
Moderator
Beiträge: 9254
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Sortieren von Spalten

Beitrag von Meillo » 03.12.2009 20:54:01

Wenn du einen awk-Shebang willst, dann musst du den Separator im BEGIN-Block definieren, denn

Code: Alles auswählen

#!/usr/bin/awk -F';' -f
funktioniert bei Linux nicht. (FreeBSD ist das einzige mir bekannte System auf dem das geht.)

Siehe dazu: http://marmaro.de/docs/freiesmagazin/sh ... hebang.pdf (Insbesondere Seite 3)
Use ed once in a while!

tuxfreund
Beiträge: 58
Registriert: 01.12.2009 19:19:46

Re: Sortieren von Spalten

Beitrag von tuxfreund » 03.12.2009 21:09:50

Hi,

jetzt hats mich fast vom Hocker gehauen. Könnte Freudentänze machen.
Es funktionier! Die Vermutung ist richtig, wir müssen das script noch anpassen. Die NULL hat nämlich eine sehr wichtige Bedeutung: Sie sagt uns, das diese Zeile jetzt noch nicht mehrfach vorkommt. Deshalb dürfen wir sie weder gruppieren noch löschen. Weil der Status sich vielleicht noch ändern wird.

Bitte noch ein kleiner Tip dazu.

Benutzeravatar
Meillo
Moderator
Beiträge: 9254
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Sortieren von Spalten

Beitrag von Meillo » 03.12.2009 21:16:32

tuxfreund hat geschrieben:Die NULL hat nämlich eine sehr wichtige Bedeutung: Sie sagt uns, das diese Zeile jetzt noch nicht mehrfach vorkommt. Deshalb dürfen wir sie weder gruppieren noch löschen. Weil der Status sich vielleicht noch ändern wird.
(Du meinst sicher die Zahl Null, also `0' ... NULL erinnert so an den NULL-Pointer oder an das Nichts in DBs.)

Statt die Zeilen mit Null zu ignorieren, sollen sie als ``eigenständig'' aufgenommen werden. So:

Code: Alles auswählen

#!/usr/bin/gawk -f
BEGIN {FS=";"}
{
        if ($3 == 0 || a[$3] == "") {
                keys[nkey++] = $3;
                a[$3] = $0;
        } else {
                a[$3] = a[$3] ORS $0;
        }
}

END {
        for (i=0; i<nkey; i++) {
                print a[keys[i]];
        }
}
Use ed once in a while!

chrisbra
Beiträge: 122
Registriert: 19.10.2005 09:36:09
Wohnort: Sachsen-Anhalt
Kontaktdaten:

Re: Sortieren von Spalten

Beitrag von chrisbra » 03.12.2009 21:57:37

Meillo hat geschrieben:Wenn du einen awk-Shebang willst, dann musst du den Separator im BEGIN-Block definieren, denn

Code: Alles auswählen

#!/usr/bin/awk -F';' -f
funktioniert bei Linux nicht. (FreeBSD ist das einzige mir bekannte System auf dem das geht.)

Siehe dazu: http://marmaro.de/docs/freiesmagazin/sh ... hebang.pdf (Insbesondere Seite 3)
Meinst Du mich? Ich hab nichts anderes geschrieben.
Meine Whishlist
:wq!

tuxfreund
Beiträge: 58
Registriert: 01.12.2009 19:19:46

Re: Sortieren von Spalten

Beitrag von tuxfreund » 03.12.2009 22:01:47

Hi
Jetzt sind alle Zeilen mit Spalte=0 überschrieben worden mit der letzten gefundenen Null-Zeile. Die Positionen sind aber richtig. Nur der Inhalt nicht.
:hail:
Gruss

Benutzeravatar
Meillo
Moderator
Beiträge: 9254
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Sortieren von Spalten

Beitrag von Meillo » 03.12.2009 22:39:39

chrisbra hat geschrieben:
Meillo hat geschrieben:

Code: Alles auswählen

#!/usr/bin/awk -F';' -f
Meinst Du mich? Ich hab nichts anderes geschrieben.
Das war nur als Ergänzung gedacht.

tuxfreund hat geschrieben:Jetzt sind alle Zeilen mit Spalte=0 überschrieben worden mit der letzten gefundenen Null-Zeile. Die Positionen sind aber richtig. Nur der Inhalt nicht.
Tja, man sollte halt besser überlegen und nicht geschwind mal was posten. (Das war 'ne Memo an mich.)

So sollte es aber gehen:

Code: Alles auswählen

#!/usr/bin/gawk -f
BEGIN {FS=";"}
{
        if ($3 == 0) {
                keys[nkey++] = "null" NR;
                a["null" NR] = $0;
        } else if (a[$3] == "") {
                keys[nkey++] = $3;
                a[$3] = $0;
        } else {
                a[$3] = a[$3] ORS $0;
        }
}

END {
        for (i=0; i<nkey; i++) {
                print a[keys[i]];
        }
}
Use ed once in a while!

tuxfreund
Beiträge: 58
Registriert: 01.12.2009 19:19:46

Re: Sortieren von Spalten

Beitrag von tuxfreund » 03.12.2009 23:17:49

So ist es jetzt perfekt Danke noch mal an alle Mitwirkenden und Mitdenker.
Ein grosses Lob!

Antworten