Sortuj plik CSV według priorytetu kolumn za pomocą polecenia „sort”

95

Mam plik csv i chciałbym posortować go według priorytetu kolumn, na przykład „kolejność według”. Na przykład:

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

Gdyby ta sytuacja była wynikiem „wyboru”, „kolejność według” wyglądałaby następująco: kolejność według kolumny2, kolumny1, kolumny3 - wynik byłby taki:

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

Chciałbym wiedzieć, jak uzyskać ten sam wynik za pomocą polecenia „sort” w systemie Unix.

Rafael Orágio
źródło
4
Nawiasem mówiąc, to jest plik ssv (wartości oddzielone średnikami): P
John Strood

Odpowiedzi:

157
sort --field-separator=';' --key=2,1,3
Charlie Martin
źródło
9
Jeśli wartości są liczbowe, prawdopodobnie zechcesz rozważyć użycie -nopcji, która „porównuje według wartości liczbowej ciągu znaków” lub -gopcji, która „porównuje według ogólnej wartości liczbowej”. Ciągowe porównanie wartości liczbowych da liczby uporządkowane w ten sposób 1,10,2,20. Przynajmniej są to opcje dostępne w mojej wersji sortowania na CentOS. Powinieneś sprawdzić na stronie podręcznika, jakie są poprawne opcje w twojej wersji sortowania.
Adam Porad,
5
Dostajęsort: stray character in field spec: invalid field specification ‘2,1,3’
Martin Thoma
3
Jednak sort --field-separator=',' -r -k3 -k1 -k2 source.csv > target.csvpracował dla mnie.
Martin Thoma,
6
@MartinThoma minęło dużo czasu, ale natknąłem się na twój problem i znalazłem to sort --field-separator=';' --key={2,1,3}. To działało GNU coreutils 8.4od kwietnia 2016 r.
mrbolichi
3
@mrbolichi notacja --key={2,1,3}używa rozszerzenia nawiasów klamrowych bash
kvantour
29

Załóżmy, że 3;10;3w unsorted.csvpliku jest inny wiersz . Myślę, że spodziewasz się wyniku posortowanego numerycznie:

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

a nie alfabetycznie:

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

Aby to uzyskać, musisz użyć -n:

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

Warto wspomnieć, że 2,2należy z niego skorzystać. Gdyby tylko2 jest używany, sortpobiera ciąg od początku pola 2 do końca. 2,2upewnia się, że 2używane jest tylko pole .

Martin Thoma
źródło
8
Wskaźnik różnicy między -k 2 a -k 2,2 jest znaczący! Przeoczyłem to podczas pierwszego czytania strony podręcznika. Dzięki.
usonianhorizon
Dodałem kilka dodatkowych wierszy, 3;10;3, 3:10:5, 3:10;2, 3;10;3w tej kolejności w pliku źródłowym, a przy użyciu tylko -k 2,2 wydaje się, aby posortować kolumny 2 i 3. Na stronie mówi mężczyzna "The -k option may be specified multiple times, in which case subsequent keys are compared when earlier keys compare equal.". W moim przypadku wcześniejszy klucz (wartość = 10) porównywał się równo, jednak nie podawałem go -kwielokrotnie. Nie jestem pewien, czy jest to niezawodne zachowanie lub związane z moim systemem (Mac). Ostatecznie nie ma to jednak znaczenia, o ile pierwotne sortowanie jest prawidłowe.
Davos
Och, widzę, jest też -sstabilny rodzaj, który ignoruje równe klucze, który według człowieka jest najwyraźniej szybszy.
Davos
24

Powyższa odpowiedź Charliego nie zadziałała dla mnie na Cygwin (wersja sortowania 2.0, GNU textutils), co zadziałało:

sort -t"," -k2 -k1 -k1
Samuel Kerrien
źródło
3
Cygwin ma starszą wersję rodzaju. Jak zawsze, strona podręcznika jest Twoim przyjacielem.
Charlie Martin
2
Zgadzam się z @CharlieMartin, powinieneś sprawdzić stronę podręcznika w swoim systemie. Na CentOS użyłemsort --field-separator=';' -k2 -k1 -k3 test.csv
Adam Porad
-6

..i jeśli ktoś zastosował rozwiązanie „sort”, ale teraz chce uzyskać więcej niż jeden unikalny wpis w wierszu (tj. X górnych liczb unikalnych wpisów), po posortowaniu pliku za pomocą polecenia „sort” można użyć mała aplikacja, którą stworzyłem tutaj:

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

Daniel Iversen
źródło
2
Dobrze dla ciebie! Ale w twoim przypadku możesz po prostu użyć cat unsorted-file | sort | uniq | head -X- kiedy Xjest liczbą pierwszych wierszy, które chcesz wyprowadzić.
Slavik Meltser
@SlavikMe Wielkie dzięki za komentarz! Jednak Twoja sugestia daje inny wynik. Twoja sugestia otrzymuje pierwsze X wierszy w całkowicie posortowanym pliku, podczas gdy chcieliśmy uzyskać pierwsze X wierszy na „klucz” (tj. Jeśli masz plik CSV z nazwami, to jeśli posortujesz według kolumny 2 „nazwisko”, wtedy twoje polecenia otrzymałyby prawdopodobnie tylko 3 wiersze z „Allen” jako ostatnim nazwiskiem, podczas gdy nasze otrzymałyby „Allen”, „Brittain”, „Charles” itp.). W każdym razie dzięki!
Daniel Iversen
6
mylisz się. Sugerowałbym wypróbowanie polecenia, które napisałem przed komentarzem. Zwróć uwagę, że istnieje polecenie uniqw kolejności potoków, między a sorti head, które nadaje niepowtarzalność wszystkim posortowanym wierszom tuż przed wyodrębnieniem górnych wierszy.
Slavik Meltser