Jaka jest różnica między „sort -u” a „sort | uniq ”?

119

Wszędzie widzę kogoś, kto musi uzyskać posortowaną, unikalną listę, do której zawsze przesyła sort | uniq. Nigdy nie widziałem żadnych przykładów, w których ktoś używa sort -uzamiast tego. Dlaczego nie? Jaka jest różnica i dlaczego do sortowania lepiej jest używać uniq niż unikalnej flagi?

Benubird
źródło

Odpowiedzi:

119

sort | uniqistniał wcześniej sort -ui jest kompatybilny z szerszą gamą systemów, chociaż prawie wszystkie nowoczesne systemy obsługują -u- to POSIX. Jest to przeważnie powrót do czasów, kiedy sort -unie istniały (a ludzie nie mają tendencji do zmiany metod, jeśli znany im sposób działa, wystarczy spojrzeć na ifconfigvs. ipadopcję).

Oba zostały prawdopodobnie połączone, ponieważ usuwanie duplikatów w pliku wymaga sortowania (przynajmniej w standardowym przypadku) i jest niezwykle częstym przypadkiem użycia. Jest także szybszy wewnętrznie, ponieważ jest w stanie wykonywać obie operacje jednocześnie (i ponieważ nie wymaga IPC pomiędzy uniqi sort). Zwłaszcza jeśli plik jest duży, sort -uprawdopodobnie użyje mniej plików pośrednich do sortowania danych.

W moim systemie konsekwentnie otrzymuję takie wyniki:

$ dd if=/dev/urandom of=/dev/shm/file bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 8.95208 s, 11.7 MB/s
$ time sort -u /dev/shm/file >/dev/null

real        0m0.500s
user        0m0.767s
sys         0m0.167s
$ time sort /dev/shm/file | uniq >/dev/null

real        0m0.772s
user        0m1.137s
sys         0m0.273s

To również nie maskować kodu powrotu sort, co może być ważne (w nowoczesnych pocisków istnieją sposoby, aby uzyskać to, na przykład, bashjest $PIPESTATUStablicą, ale nie zawsze było to prawdą).

Chris Down
źródło
31
Mam tendencję do używania, sort | uniqponieważ 9 razy na 10, właściwie lecę do uniq -c.
Plutor
5
Zauważ, że sort -ubył częścią 7. edycji UNIX, około 1979 roku. Wersje sortbez wsparcia dla -usą naprawdę archaiczne - lub zostały napisane bez zwracania uwagi na faktyczny standard przed standardem de jure POSIX. Zobacz także Stack Overflow Sort & uniq w powłoce Linux z 2010 roku.
Jonathan Leffler
3
+1 z powodu ip. Jest rok 2016 i ten post w 2013 roku, ale teraz wiem tylko o ipdowodzeniu.
dieend
4
+1 za „9 razy na 10, które aktualnie przesyłam uniq -c” (a może jeszcze raz przesyłam sort -nr | head). Zastanawiałem się, co jest sort | uniqw Vimie, kiedy dowiedziałem się, że Vim ma :sort udowodzenie. I sort -uistnieje również TIL .
Zhuoyun Wei
Należy pamiętać, że istnieje różnica przy użyciu sort -n | uniqVs. sort -n -u. Na przykład końcowe i białe spacje będą traktowane jako duplikaty, sort -n -uale nie przez pierwsze! echo -e 'test \n test' | sort -n -uzwraca test, ale echo -e 'test \n test' | sort -n | uniqzwraca obie linie.
mxmlnkn
46

Jedną różnicą jest to, że uniqma wiele przydatnych dodatkowych opcji, takich jak pomijanie pól w celu porównania i zliczanie liczby powtórzeń wartości. sort„s -uflag realizuje tylko funkcjonalność ozdób uniqpolecenia.

CLF
źródło
3
+0,49 za przydatną odpowiedź, ale sformułowałbym coś w stylu „Wyjścia sort -unie można przekazać, uniqaby użyć niektórych przydatnych opcji tego ostatniego, takich jak pomijanie pól w celu porównania i zliczanie liczby powtórzeń”.
l0b0
15
+1 do zrekompensowania naysayers bo „nie ma sposobu, aby to zrobić bezpośrednio z rodzaju” ma odpowiedzieć na pytanie ...
Izkata
42

W przypadku sorts i uniqs zgodnych z POSIX (GNU uniqjest obecnie niezgodny w tym względzie), istnieje różnica w tym, że sortużywa algorytmu zestawiania ustawień regionalnych do porównywania ciągów (zwykle używa strcoll()do porównywania ciągów), podczas gdy uniqsprawdza tożsamość wartości bajtowej (zwykle używa strcmp()) .

Ma to znaczenie z co najmniej dwóch powodów.

  • W niektórych lokalizacjach, szczególnie w systemach GNU, istnieją różne znaki, które sortują to samo. Na przykład w ustawieniach narodowych en_US.UTF-8 w systemie GNU wszystkie znaki ①②③④⑤⑥⑦⑧⑨⑩ ... i wiele innych sortują to samo, ponieważ ich kolejność sortowania nie jest zdefiniowana. Cyfry arabskie 0123456789 są sortowane tak samo, jak ich odpowiedniki w języku arabskim wschodnim (٠١٢٣٤٥٦٧٨٩).

    Dla sort -u① sortuje to samo co ②, a 0123 to samo co ٠١٢٣, więc sort -uzachowałby tylko jeden z nich, podczas gdy dla uniq(nie GNU, uniqktóry używa strcoll()(oprócz -i)), ① różni się od ② i 0123 różni się od ٠١٢٣, więc uniqrozważa wszystko 4 unikalne.

  • strcollmoże porównywać tylko ciągi prawidłowych znaków (zachowanie jest niezdefiniowane zgodnie z POSIX, gdy dane wejściowe zawierają sekwencje bajtów, które nie tworzą prawidłowych znaków), podczas gdy strcmp()nie przejmuje się znakami, ponieważ dokonuje tylko porównania bajt-bajt. To kolejny powód, dla którego sort -umożesz nie podać wszystkich unikalnych wierszy, jeśli niektóre z nich nie tworzą poprawnego tekstu. sort|uniq, chociaż nadal nie jest określony w przypadku wprowadzania nietekstowego, w praktyce jest bardziej prawdopodobne, że podadzą ci unikalne wiersze z tego powodu.

Obok tych subtelności, jedna rzecz, która nie odnotowano do tej pory jest to, że uniqporównuje całą linię leksykalnie, podczas gdy sort„s -uporównano na podstawie specyfikacji danego sortowania w wierszu poleceń.

$ printf '%s\n' 'a b' 'a c' | sort -uk 1,1
a b
$ printf '%s\n' 'a b' 'a c' | sort -k 1,1 | uniq
a b
a c

$ printf '%s\n' 0 -0 +0 00 '' | sort -n | uniq
0
-0
+0
00

$ printf '%s\n' 0 -0 +0 00 '' | sort -nu
0
Stéphane Chazelas
źródło
9

Wolę używać, sort | uniqponieważ kiedy próbuję użyć opcji -u(wyeliminuj duplikaty), aby usunąć duplikaty zawierające mieszane ciągi znaków, nie jest łatwo zrozumieć wynik.

Uwaga: zanim będziesz mógł uruchomić poniższe przykłady, musisz zasymulować standardową sekwencję zestawiania C, wykonując następujące czynności:

LC_ALL=C
export LC_ALL

Na przykład, jeśli chcę posortować plik i usunąć duplikaty, zachowując jednocześnie odrębność różnych przypadków ciągów.

$ cat short      #file to sort
Pear
Pear
apple
pear
Apple

$ sort short     #normal sort (in normal C collating sequence)
Apple            #the lower case words are at the end
Pear
Pear
apple
pear

$ sort -f short  #correctly sorts ignoring the C collating order
Apple            #but duplicates are still there
apple
Pear
Pear
pear

$ sort -fu short #By adding the -u option to remove duplicates it is 
apple            #difficult to ascertain the logic that sort uses to remove
Pear             #duplicates(i.e., why did it remove pear instead of Pear?)

To zamieszanie rozwiązuje się, nie wykorzystując -uopcji usuwania duplikatów. Korzystanie uniqjest bardziej przewidywalne. Poniżej najpierw sortuje i ignoruje obudowę, a następnie przekazuje ją uniqdo usunięcia duplikatów.

$ sort -f short | uniq
Apple
apple
Pear
pear
Jerry Marbas
źródło
2
-uopcja sortwyjścia pierwszego równego przebiegu (patrz strona man). W ten sposób sort -fuodbiera się pierwsze wystąpienie każdej unikalnej linii bez rozróżniania wielkości liter. Logika sortużywana do usuwania duplikatów jest przewidywalna.
pallxk
3

Kolejną różnicą, którą dzisiaj odkryłem, jest to, że podczas sortowania w oparciu o delimetr sort -ustosuje się unikalną flagę tylko do kolumny, którą sortujesz.

$ cat input.csv
3,World,1
1,Hello,1
2,Hello,1

$ cat input.csv | sort -t',' -k2 -u
1,Hello,1
3,World,1

$ cat input.csv | sort -t',' -k2 | uniq
1,Hello,1
2,Hello,1
3,World,1
Stefanos Chrs
źródło
Wspomniano o tym w odpowiedzi Stéphane'a Chazelasa, ale podoba mi się twój przykład, więc +1
roaima
Dzięki za wskazanie @roaima, odpowiedź nie była bardzo jasna
Stefanos Chrs