Sortieren mehrerer Schlüssel mit Unix-Sortierung

137

Ich habe möglicherweise große Dateien, die nach 1-n-Schlüsseln sortiert werden müssen. Einige dieser Tasten sind möglicherweise numerisch, andere möglicherweise nicht. Dies ist eine Säulendatei mit fester Breite, daher gibt es keine Trennzeichen.

Gibt es eine gute Möglichkeit, dies mit Unix sort zu tun? Mit einem Schlüssel ist es so einfach wie mit '-n'. Ich habe die Manpage gelesen und kurz bei Google gesucht, aber kein gutes Beispiel gefunden. Wie würde ich vorgehen, um dies zu erreichen?

Hinweis: Ich habe Perl aufgrund des Potenzials der Dateigröße ausgeschlossen. Es wäre ein letzter Ausweg.

Chris Kloberdanz
quelle
Eine oder zwei Zeilen mit Beispieldaten wären sehr hilfreich, um eine Beispielbefehlszeile zu erstellen. Bedeutet "1-n" Schlüssel auch, dass Sie nach einer variablen Anzahl von Schlüsseln sortieren müssen? Das ohne Scripting zu machen wird Spaß machen ...
Ken Gentle
Ich habe einen PHP-Wrapper um den Sortierbefehl, um die 1-n-Funktion zu aktivieren.
Chris Kloberdanz

Antworten:

69

Verwenden Sie die -kOption (oder --key=POS1[,POS2]). Es kann mehrmals angezeigt werden und jeder Schlüssel kann globale Optionen haben (z. B. nfür die numerische Sortierung).

Ken Gentle
quelle
7
Auf der Sortier-Manpage: "POS ist F [.C] [OPTS], wobei F die Feldnummer und C die Zeichenposition im Feld ist; beide sind Ursprung 1." Eine vollständige Dokumentation finden Sie in der Manpage.
Adam Rosenfield
49
Siehe auch andras 'Antwort, wenn du nicht verrückt werden willst.
Ron
1
Beide obigen Kommentare sind korrekt und additiv. Danke, meine Herren.
Ken Gentle
314

Pass aber auf:

Wenn Sie die Datei hauptsächlich nach Feld 3 und sekundär nach Feld 2 sortieren möchten, möchten Sie Folgendes:

sort -k 3,3 -k 2,2 < inputfile

Nicht dies: sort -k 3 -k 2 < inputfile Hiermit wird die Datei nach der Zeichenfolge vom Anfang von Feld 3 bis zum Zeilenende sortiert (was möglicherweise eindeutig ist).

-k, --key=POS1[,POS2]     start a key at POS1 (origin 1), end it at POS2
                          (default end of line)
andras
quelle
8
Das Leben verändert sich. Vielen Dank.
Davidtbernal
2
Hoppla! Jetzt muss ich ein Skript reparieren, da ich früher nur die erste Antwort oben gesehen habe ... gut, dass ich noch nicht von der Skriptausgabe abhängig war ...
Wildcard
Nett! Was ist nun, wenn ich möchte, dass Feld 3 numerisch und umgekehrt sortiert wird, während Feld 2 nicht numerisch und normal (aufsteigend) sortiert ist? :)
Arun
2
@Arun POS wird am Ende der Manpage erklärt. Sie hängen die Bestelloptionen einfach wie sort -k 3,3nr -k 2,2
folgt
1
Aargh. Was für eine kontraintuitive Schnittstelle: -k2sollte sein -k2,2und ein nachfolgendes Komma -k2,sollte "magisches Standardzeilenende oder was auch immer" sein.
android.weasel
94

Die Option -k ist genau das, was Sie wollen.

-k 1.4,1.5n -k 1.14,1.15n

Würde die Zeichenpositionen 4-5 im ersten Feld verwenden (es ist alles ein Feld für feste Breite) und numerisch als ersten Schlüssel sortieren.

Der zweite Schlüssel wären auch die Zeichen 14-15 im ersten Feld.

(bearbeiten)

Beispiel (alles was ich habe ist DOS / Cygwin praktisch):

dir | \cygwin\bin\sort.exe -k 1.4,1.5n -k 1.40,1.60r

für die Daten:

12/10/2008  01:10 PM         1,564,990 outfile.txt

Sortiert die Verzeichnisliste numerisch nach Monatsnummer (Pos. 4-5) und umgekehrt nach Dateiname (Pos. 40-60). Da es keine Registerkarten gibt, muss Feld 1 sortiert werden.

Clinton Pierce
quelle
Es ist nur ein Feld, wenn die Eingabedaten keine Leerzeichen enthalten. Trotzdem ist Ihr Beispiel nützlich.
Jonathan Leffler
Korrektur: Wenn die Eingabedaten keine / tabs / enthalten. In der DOS-Befehlsausgabe 'dir' gibt es keine Registerkarten.
Clinton Pierce
Die Beispiele zur Verwendung der Optionen (numerisch, umgekehrt) sind äußerst hilfreich, da es fast unmöglich ist, die Verwendung nur auf der Manpage herauszufinden, und die anderen Antworten dies nicht erwähnt haben. Ich wünschte ich könnte +2 dafür. ;)
msb
22

Hier ist eine, um verschiedene Spalten in einer CSV-Datei nach numerischer und Wörterbuchreihenfolge, Spalten 5 und danach als Wörterbuchreihenfolge zu sortieren

~/test>sort -t, -k1,1n -k2,2n -k3,3d -k4,4n -k5d  sort.csv
1,10,b,22,Ga
2,2,b,20,F
2,2,b,22,Ga
2,2,c,19,Ga
2,2,c,19,Gb,hi
2,2,c,19,Gb,hj
2,3,a,9,C

~/test>cat sort.csv
2,3,a,9,C
2,2,b,20,F
2,2,c,19,Gb,hj
2,2,c,19,Gb,hi
2,2,c,19,Ga
2,2,b,22,Ga
1,10,b,22,Ga

Beachten Sie, dass -k1,1n numerisch bedeutet, beginnend mit Spalte 1 und endend mit Spalte 1. Wenn ich es unten getan hätte, hätte es Spalte 1 und 2 verkettet und 1,10 als 110 sortiert

~/test>sort -t, -k1,2n -k3,3 -k4,4n -k5d  sort.csv
2,2,b,20,F
2,2,b,22,Ga
2,2,c,19,Ga
2,2,c,19,Gb,hi
2,2,c,19,Gb,hj
2,3,a,9,C
1,10,b,22,Ga
edW
quelle
1
Dies ist die beste Antwort, weil es zeigt, wie man verschiedene Schalter für verschiedene Spalten verwendet
xaxa
12

Ich glaube an deinen Fall so etwas wie

sort -t@ -k1.1,1.4 -k1.5,1.7 ... <inputfile

wird besser funktionieren. @ ist das Feldtrennzeichen. Stellen Sie sicher, dass es sich um ein Zeichen handelt, das nirgendwo erscheint. dann wird Ihre Eingabe als aus einer Spalte bestehend betrachtet.

Edit: anscheinend hat clintp schon eine ähnliche antwort gegeben, sorry. Wie er betont, können die Flags 'n' und 'r' zu jeder Option -k .... hinzugefügt werden.

Dong Hoon
quelle
Obwohl das Standardtrennzeichen für docs gnu.org/software/coreutils/manual/html_node/… Leerzeichen ist, entspricht die Feldanzahl manchmal nicht Ihren Erwartungen. Vielleicht, wie andere hier gesagt haben, wegen der Gebietsschemaeinstellung LC_CTYPE. Im Zweifelsfall vom Anfang der Zeile an zählen!
Brad Dre
5

Es ist zu beachten, dass dies auch erwünscht sein kann, um die Sortierung mit dem -sSchalter zu stabilisieren , so dass gleichrangige Linien auch in der Ausgabe ihre ursprüngliche relative Reihenfolge beibehalten.

Ron
quelle
2

Ich möchte nur einige Tipps hinzufügen. Wenn Sie sort verwenden, achten Sie auf Ihr Gebietsschema, das sich auf die Reihenfolge des Schlüsselvergleichs auswirkt. Normalerweise verwende ich explizit LC_ALL = C, um das Gebietsschema so zu gestalten, wie ich es möchte.

jianpx
quelle
LC_ALL = C kann auch zu einer ziemlichen Beschleunigung führen!
Mat Kelcey