Sortieren Sie die CSV-Datei mit dem Befehl "sort" nach Spaltenpriorität

91

Ich habe eine CSV-Datei und möchte sie nach Spaltenpriorität sortieren, z. B. "Sortieren nach". Beispielsweise:

3;1;2
1;3;2
1;2;3
2;3;1
2;1;3
3;2;1

Wenn diese Situation das Ergebnis einer "Auswahl" wäre, wäre die "Reihenfolge nach" wie folgt: Reihenfolge nach Spalte2, Spalte1, Spalte3 - das Ergebnis wäre:

2;1;3
3;1;2
1;2;3
3;2;1
1;3;2
2;3;1

Ich würde gerne wissen, wie man dasselbe Ergebnis mit dem Befehl "sort" unter Unix erzielt.

Rafael Orágio
quelle
4
Übrigens, das ist eine SSV-Datei (durch Semikolons getrennte Werte): P
John Strood

Antworten:

153
sort --field-separator=';' --key=2,1,3
Charlie Martin
quelle
8
Wenn die Werte numerisch sind, sollten Sie wahrscheinlich die -nOption verwenden, die "nach dem numerischen Wert der Zeichenfolge vergleichen" oder die -gOption "nach dem allgemeinen numerischen Wert vergleichen". Bei einem Zeichenfolgenvergleich numerischer Werte werden die Zahlen wie folgt sortiert 1,10,2,20. Zumindest sind dies Optionen, die in meiner Sortierversion unter CentOS verfügbar sind. Sie sollten anhand der Manpage überprüfen, welche Optionen in Ihrer Sortierversion korrekt sind.
Adam Porad
4
Ich bekommesort: stray character in field spec: invalid field specification ‘2,1,3’
Martin Thoma
3
Hat aber sort --field-separator=',' -r -k3 -k1 -k2 source.csv > target.csvfür mich gearbeitet.
Martin Thoma
1
Dies würde niemals für echte CSV-Dateien funktionieren, die ein Feldtrennzeichen in der Spalte enthalten
user121196
5
@ MartinThoma Es ist lange her, aber ich bin auf dein Problem gestoßen und habe das gefunden sort --field-separator=';' --key={2,1,3}. Dies funktionierte GNU coreutils 8.4ab April 2016
Mrbolichi
28

Angenommen, Sie haben eine weitere Zeile 3;10;3in Ihrer unsorted.csvDatei. Dann erwarten Sie vermutlich ein numerisch sortiertes Ergebnis:

2;1;3
3;1;2
1;2;3
3;2;1
1;3;2
2;3;1
3;10;3

und nicht alphabetisch sortiert:

2;1;3
3;1;2
3;10;3
1;2;3
3;2;1
1;3;2
2;3;1

Um das zu bekommen, müssen Sie verwenden -n:

sort --field-separator=';' -n -k 2,2 -k 1,1 -k 3,3 unsorted.csv

Es ist erwähnenswert, dass 2,2verwendet werden muss. Wenn nur 2verwendet wird, sortwird die Zeichenfolge vom Anfang von Feld 2 bis zum Ende übernommen. 2,2stellt sicher, dass nur das Feld 2verwendet wird.

Martin Thoma
quelle
7
Der Zeiger auf den Unterschied zwischen -k 2 und -k 2,2 ist signifikant! Ich hatte dies bei meiner ersten Lesung der Manpage übersehen. Vielen Dank.
Usonianhorizon
Ich habe ein paar zusätzliche Zeilen 3;10;3, 3:10:5, 3:10;2, 3;10;3in dieser Reihenfolge in der Quelldatei, und bei der Verwendung nur -k 2,2 auf Spalte 2 und 3. Die Manpage sagt zu sortieren erscheint "The -k option may be specified multiple times, in which case subsequent keys are compared when earlier keys compare equal.". In meinem Fall war der frühere Schlüssel (Wert = 10) gleich, ich habe ihn jedoch nicht -kmehrmals angegeben. Ich bin nicht sicher, ob dies ein zuverlässiges Verhalten ist oder mit meinem System (Mac) zusammenhängt. Letztendlich spielt es jedoch keine Rolle, solange die primäre Sortierung korrekt ist.
Davos
Oh, ich sehe, es gibt auch eine -sstabile Sorte, die die gleichen Schlüssel ignoriert, die laut Mann anscheinend schneller ist.
Davos
24

Charlies Antwort oben hat bei Cygwin (Sortierversion 2.0, GNU-Textutils) bei mir nicht funktioniert. Folgendes hat funktioniert:

sort -t"," -k2 -k1 -k1
Samuel Kerrien
quelle
3
Cygwin hat eine ältere Version. Wie immer ist die Manpage dein Freund.
Charlie Martin
2
Ich stimme @CharlieMartin zu, Sie sollten die Manpage auf Ihrem System überprüfen. Auf CentOS habe ichsort --field-separator=';' -k2 -k1 -k3 test.csv
Adam Porad
-6

..und wenn jemand der 'Sortier'-Lösung gefolgt ist, aber jetzt mehr als den einzelnen eindeutigen Eintrag pro Zeile (dh die oberste X-Anzahl von eindeutigen Einträgen) erhalten möchte, können Sie die Datei verwenden, sobald Sie sie mit' sortieren 'sortiert haben eine kleine App, die ich hier erstellt habe:

https://github.com/danieliversen/MiscStuff/blob/master/scripts/findTopUniques.java

Daniel Iversen
quelle
2
Schön für dich! Aber in Ihrem Fall könnten Sie einfach verwenden cat unsorted-file | sort | uniq | head -X- wann Xist die Anzahl der ersten Zeilen, die Sie ausgeben möchten.
Slavik Meltser
@SlavikMe Vielen Dank für den Kommentar! Ihr Vorschlag liefert jedoch ein anderes Ergebnis. Ihr Vorschlag erhält die ersten X-Zeilen in der vollständig sortierten Datei, während wir die ersten X-Zeilen pro "Schlüssel" erhalten wollten (dh wenn Sie eine CSV mit Namen haben, dann, wenn Sie sortieren In Spalte 2 "Nachname" würden Ihre Befehle möglicherweise nur 3 Zeilen mit "Allen" als Nachnamen erhalten, während unsere Befehle "Allen", "Brittain", "Charles" usw. erhalten würden. Trotzdem danke!
Daniel Iversen
6
Sie liegen falsch. Ich hätte vorgeschlagen, den Befehl, den ich geschrieben habe, vor dem Kommentieren auszuprobieren. Beachten Sie, dass es einen Befehl gibtuniq zwischen sortund und in der Reihenfolge der Pipeshead , der allen sortierten Zeilen unmittelbar vor dem Extrahieren der obersten Zeilen eine Eindeutigkeit verleiht.
Slavik Meltser