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ść.


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)


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)

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.


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

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 ....


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.


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ę.


LC_ALL = C może również spowodować spore przyspieszenie!
— mat kelcey
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.