Wie mache ich eine benutzerdefinierte Sortierung mit Unix-Sortierung?

11

Ich verwende die Unix-Sortierung, um eine durch Kommas getrennte Datei mit mehreren Spalten zu sortieren. Bisher hat dies perfekt funktioniert, um die Daten entweder numerisch oder in alphabetischer Reihenfolge zu sortieren:

Beispieldatei vor dem Sortieren:

C,United States,WA,Tacoma,f,1
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2
A,United States,NY,New York,f,1

Sortieren Sie die Datei: $ sort -t ',' -k 2,2 -k 3,3 -k 4,4 -k 5,5r -k 6,6nr tmp.csv

Sortiertes Ergebnis:

A,Bahamas,Bahamas,Nassau,f,2
A,Canada,QC,Montreal,f,2
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1

Hier ist das Problem: Ich möchte Spalte 2 nach einer benutzerdefinierten Sortierung sortieren, dh ich möchte zuerst die USA, dann Kanada und dann die Bahamas:

Gewünschte Sorte:

A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2

Gibt es eine Möglichkeit, Unix-Sortierung eine benutzerdefinierte Sortierreihenfolge zu übergeben, die dann angewendet werden kann? Etwas wie: $ sort -t ',' -k 2,2:'United States, Canada, Bahamas' -k 3,3 -k 4,4 -k 5,5r -k 6,6nr tmp.csv

Vielen Dank!


quelle
3
Für diese drei Werte möchten Sie eine umgekehrte alphabetische Reihenfolge. Für den allgemeinen Fall müssen Sie die Namen einer Sortierreihenfolge zuordnen und dann die Sortierung anhand der Sortierreihenfolge durchführen. Oder wählen Sie eine Skriptsprache ... Eine Möglichkeit ist der joinBefehl, aber Sie könnten viel sortieren - die Eingabedateien für joinmüssen in einer Reihenfolge sortiert werden, und dann würden Sie sie sorterneut verwenden, um die Daten zu speichern eine andere Reihenfolge (und Verlust der Spalte für die Sortierreihenfolge als Schritt nach der Sortierung).
Jonathan Leffler
Sollte es in Ihrer Beispieleingabe nicht tstatt fin der letzten Zeile geben?
Lev Levitsky
Lev: Ja, guter Fang. Mein Fehler; zu viel Ausschneiden und Einfügen (mein tatsächlicher Datensatz ist viel größer und ich habe versehentlich die falschen Zeilen gepackt).
Ich habe die Antwort aktualisiert, um sie an Ihre Daten anzupassen.
Lev Levitsky

Antworten:

8

Die andere Antwort und der andere Kommentar beantworten die Frage im Allgemeinen. So kann eine Implementierung aussehen:

$ cat order
Bahamas,3
Canada,2
United States,1

$ cat data
C,United States,WA,Tacoma,f,1
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2
A,United States,NY,New York,f,1

$ sort -t, -k2 data | join -t, -11 -22 order - | sort -t, -k2n -k4,5 -k6r -k7nr | cut -d, -f 3,1,4-7
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2
Lev Levitsky
quelle
Super, danke für deine Hilfe. Das hat perfekt funktioniert!
@jewelia Noch einmal verbessert, sedwurde hier nicht wirklich gebraucht.
Lev Levitsky
1

Das kann man mit sort nicht machen . An diesem Punkt sollten Sie wirklich nach awk / perl / Ihrer Sprache Ihrer Wahl greifen . Sie können es jedoch fummeln. Sie können beispielsweise sed verwenden, um "USA" in 0, "Kanada" in 1 und "Bahamas" in 2 zu ändern, dann eine numerische Sortierung für diese Spalte durchzuführen und sie dann zurückzusetzen. Oder ändern Sie "USA" in "USA, 0" usw., sortieren Sie nach der zusätzlichen Spalte und verwerfen Sie sie dann.

itsbruce
quelle
0

Ich habe gerade einen Helfer namens csort geschrieben , um dies zu vereinfachen. Jeder Zeile wird ein Wert Ihrer Wahl vorangestellt, der auf Übereinstimmungen mit Teilzeichenfolgen oder regulären Ausdrücken innerhalb der Zeile basiert:

$ csort -t, '2=United States' X 2=Canada Y 2=Bahamas Z < tmp.csv | \
sort -t, -k1,1 -k3,3 -k4,4 -k5,5 -k6,6r -k7,7nr
X,A,United States,MA,Boston,f,0
X,B,United States,NY,New York,f,5
X,A,United States,NY,New York,f,1
X,C,United States,WA,Tacoma,f,1
Y,A,Canada,QC,Montreal,f,2
Z,A,Bahamas,Bahamas,Nassau,f,2

Die 2=STRNotation bedeutet "Übereinstimmung, wenn das zweite Feld gleich ist STR".

Sie können die Ausgabe dann optional weiterleiten cut -c3-, um das Präfix zu entfernen.

Adam Spires
quelle