Sortowanie wielu kluczy za pomocą sortowania Unix

137

Mam potencjalnie duże pliki, które muszą być sortowane według 1-n kluczy. Niektóre z tych kluczy mogą być numeryczne, a niektóre nie. Jest to plik kolumnowy o stałej szerokości, więc nie ma ograniczników.

Czy jest dobry sposób na zrobienie tego z sortowaniem w systemie Unix? Z jednym klawiszem jest to tak proste, jak użycie „-n”. Przeczytałem stronę podręcznika i krótko przeszukałem Google, ale nie znalazłem dobrego przykładu. Jak bym się do tego zabrał?

Uwaga: wykluczyłem Perla ze względu na potencjalny rozmiar pliku. To byłaby ostateczność.

Chris Kloberdanz
źródło
Jeden lub dwa wiersze przykładowych danych byłyby naprawdę pomocne przy tworzeniu przykładowego wiersza poleceń. Poza tym, czy klucze „1-n” oznaczają, że trzeba sortować według zmiennej liczby kluczy? Robienie tego bez skryptów będzie fajne ...
Ken Gentle,
Mam otokę PHP wokół polecenia sortowania, aby włączyć funkcję 1-n.
Chris Kloberdanz

Odpowiedzi:

69

Użyj -kopcji (lub --key=POS1[,POS2]). Może pojawić się wiele razy, a każdy klucz może mieć opcje globalne (takie jak nsortowanie numeryczne)

Ken Gentle
źródło
7
Ze strony podręcznika sortowania: "POS to F [.C] [OPTS], gdzie F to numer pola, a C to pozycja znaku w polu; oba są początkiem 1." Pełna dokumentacja znajduje się na stronie podręcznika.
Adam Rosenfield,
49
Zobacz także odpowiedź Andrasa, jeśli nie chcesz oszaleć.
ron
1
Oba powyższe uwagi są dokładne i uzupełniające. Dzięki, panowie.
Ken Gentle,
314

Uważaj jednak:

Jeśli chcesz posortować plik głównie według pola 3, a po drugie według pola 2, chcesz to:

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

Nie to: sort -k 3 -k 2 < inputfile które sortuje plik według ciągu od początku pola 3 do końca wiersza (który jest potencjalnie unikalny).

-k, --key=POS1[,POS2]     start a key at POS1 (origin 1), end it at POS2
                          (default end of line)
andras
źródło
8
Zmieniający życie. Dzięki.
davidtbernal
2
Ups! Teraz muszę naprawić skrypt, ponieważ wcześniej widziałem tylko pierwszą odpowiedź powyżej ... dobrze, że jeszcze nie polegałem na wynikach skryptu ....
Wildcard
Miły! A co, jeśli chcę, aby obszar 3 był sortowany numerycznie i odwrotnie, podczas gdy pole 2 było sortowane nieliczbowo i normalnie (rosnąco)? :)
Arun
2
@Arun POS jest wyjaśnione na końcu strony podręcznika. Wystarczy dołączyć opcje zamówienia do numeru pola w następujący sposób:sort -k 3,3nr -k 2,2
andras
1
Aargh. Cóż za sprzeczny z intuicją interfejs: -k2powinien być, -k2,2a końcowy przecinek -k2,powinien oznaczać „magiczny domyślny koniec wiersza lub cokolwiek innego”.
android.weasel
94

Opcja -k jest tym, czego chcesz.

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

Użyłby pozycji 4-5 znaków w pierwszym polu (jest to jedno pole o stałej szerokości) i posortowałby numerycznie jako pierwszy klucz.

Drugi klucz również będzie zawierał znaki 14-15 w pierwszym polu.

(edytować)

Przykład (wszystko co mam to DOS / cygwin pod ręką):

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

dla danych:

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

Sortuje listę katalogów według numeru miesiąca (poz. 4-5), a następnie odwrotnie według nazwy pliku (poz. 40-60). Ponieważ nie ma żadnych zakładek, sortowanie zajmuje całe pole 1.

Clinton Pierce
źródło
Jest to tylko jedno pole, jeśli w danych wejściowych nie ma spacji. Niemniej jednak twój przykład jest przydatny.
Jonathan Leffler,
Korekta: jeśli w danych wejściowych nie ma / zakładek /. W wyjściu polecenia „dir” systemu DOS nie ma zakładek.
Clinton Pierce,
Przykłady użycia opcji (numeryczne, odwrotne) są niezwykle pomocne, ponieważ prawie niemożliwe jest, aby dowiedzieć się, jak używać tylko ze strony podręcznika, a inne odpowiedzi o tym nie wspominają. Chciałabym móc +2 za to. ;)
msb
22

Oto jeden do sortowania różnych kolumn w pliku csv według kolejności numerycznej i słownika, kolumny 5 i później w porządku słownikowym

~/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

Zwróć uwagę, że -k1,1n oznacza numeryczne zaczynające się od kolumny 1 i kończące się w kolumnie 1. Gdybym zrobił to poniżej, połączyłoby to kolumny 1 i 2, co 1,10 posortowałoby jako 110

~/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
źródło
1
To najlepsza odpowiedź, ponieważ pokazuje, jak używać różnych przełączników dla różnych kolumn
xaxa
12

Wierzę w twoim przypadku w coś takiego

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

będzie działać lepiej. @ to separator pól, upewnij się, że jest to znak, który nigdzie nie występuje. wtedy twoje wejście jest traktowane jako składające się z jednej kolumny.

Edycja: najwyraźniej clintp udzielił już podobnej odpowiedzi, przepraszam. Jak wskazuje, flagi 'n' i 'r' można dodać do każdej opcji -k ....

Dong Hoon
źródło
Mimo że domyślnym separatorem zgodnie z docs gnu.org/software/coreutils/manual/html_node/… jest spacja, czasami liczba pól nie jest tym, czego można się spodziewać. Być może tak, jak powiedzieli tu inni, z powodu ustawień regionalnych LC_CTYPE. W razie wątpliwości licz od początku wiersza!
Brad Dre,
5

Zauważ, że może być również pożądane ustabilizowanie sortowania za pomocą -sprzełącznika, tak aby równo uszeregowane linie również zachowały swoją pierwotną względną kolejność na wyjściu.

ron
źródło
2

Chcę tylko dodać kilka wskazówek, kiedy używasz sortowania, uważaj na ustawienia regionalne, które mają wpływ na kolejność porównania kluczy. Zwykle jawnie używam LC_ALL = C, aby ustawić ustawienia regionalne tak, jak chcę.

jianpx
źródło
LC_ALL = C może również spowodować spore przyspieszenie!
mat kelcey