Wszędzie, gdzie widzę, że ktoś potrzebuje posortowanej, unikalnej listy, zawsze kieruje do sort | uniq
. „Nigdy nie widziałem żadnych przykładów, w których ktoś zamiast tego używa sort -u
. Dlaczego nie? Jaka jest różnica i dlaczego do sortowania lepiej jest użyć uniq niż unikalnej flagi?
Komentarze
- aplawrence.com/Unixart/sort-vs-uniq.html
Odpowiedź
sort | uniq
istniał przed sort -u
i jest kompatybilny z szerszą gamą systemów, chociaż prawie wszystkie współczesne systemy obsługują -u
– to POSIX. To głównie powrót do czasów, kiedy sort -u
nie istniało (a ludzie nie mają tendencji do zmiany swoich metod, jeśli znany im sposób nadal działa, spójrz na ifconfig
a ip
adopcja).
Oba zostały prawdopodobnie połączone, ponieważ usuwanie duplikatów w pliku wymaga sortowania (przynajmniej w standardzie przypadek) i jest niezwykle powszechnym przypadkiem użycia. Jest również szybszy wewnętrznie dzięki możliwości wykonywania obu operacji w tym samym czasie (i ponieważ nie wymaga IPC między uniq
a sort
). Zwłaszcza jeśli plik jest duży, sort -u
prawdopodobnie użyje mniejszej liczby plików pośrednich do sortowania danych.
W moim systemie Ciągle 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
Nie maskuje też kodu powrotu sort
, który może być ważne (w nowoczesnych powłokach są sposoby, aby to uzyskać, na przykład tablica bash
„s $PIPESTATUS
, ale to nie było zawsze prawda).
Komentarze
- Zwykle używam
sort | uniq
, ponieważ 9 razy na 10 I ' m faktycznie podłączam douniq -c
. - Pamiętaj, że
sort -u
był częścią 7.edycji UNIX, około 1979 roku. Wersjesort
bez Obsługa-u
jest naprawdę archaiczna – lub została napisana bez zwracania uwagi na faktyczny standard przed standardem POSIX ' de iure. Zobacz też Przepełnienie stosu Sortuj & uniq w powłoce Linuksa od 2010 r. - +1, ponieważ z
ip
. To ' rok 2016 i ten post z 2013 r., Ale teraz wiem tylko o poleceniuip
. - +1 dla ” 9 przekroczonych limitów czasu 10 I ' m w rzeczywistości podłączam do
uniq -c
” (i być może jeszcze raz podłączam dosort -nr | head
). Zastanawiałem się, jaki jest odpowiedniksort | uniq
w Vimie, kiedy dowiedziałem się, że Vim ma polecenie:sort u
. Istnieje również TILsort -u
. - Zauważ, że istnieje różnica między
sort -n | uniq
asort -n -u
. Na przykład końcowe i początkowe białe znaki będą postrzegane jako duplikaty przezsort -n -u
, ale nie przez pierwsze!echo -e 'test \n test' | sort -n -u
zwracatest
, aleecho -e 'test \n test' | sort -n | uniq
zwraca obie linie.
Odpowiedź
Jedyną różnicą jest to, że uniq
ma wiele przydatnych dodatkowych opcji, takich jak pomijanie pól do porównania i zliczanie liczby powtórzeń wartości. Flaga sort
„s -u
implementuje tylko funkcjonalność niewykończonego polecenia uniq
.
Komentarze
- +0.49, aby uzyskać użyteczną odpowiedź, ale powiedziałbym coś w stylu ” Wynik
sort -u
nie może ' nie zostać przekazane douniq
, aby użyć drugiego ' użytecznych opcji, takich jak pomijanie pól do porównania i liczenie liczby powtórzeń. ” - +1 do naysayers, ponieważ ” tam ' nie ma możliwości zrobienia tego bezpośrednio z sortowania ” czy odpowiada na pytanie …
Odpowiedź
Ze zgodnym z POSIX sort
s i uniq
s (GNU uniq
jest obecnie niezgodne w tym zakresie), jest różnica w tym, że sort
używa algorytmu zestawiania ustawień regionalnych do porównywania ciągów (zazwyczaj używa strcoll()
do porównywania ciągów), podczas gdy uniq
sprawdza tożsamość wartości bajtowej (zazwyczaj używa strcmp()
) ¹.
Ma to co najmniej dwa powody .
-
W niektórych lokalizacjach, szczególnie w systemach GNU, istnieją różne znaki, które sortują to samo. Na przykład w lokalizacji en_US.UTF-8 w systemie GNU wszystkie ①②③④⑤⑥⑦⑧⑨⑩ … znaki² i wiele innych są sortowane tak samo, ponieważ ich kolejność sortowania nie jest zdefiniowana. Cyfry arabskie 0123456789 są sortowane tak samo, jak ich odpowiedniki w wschodnio-arabskich i indyjskich (٠١٢٣٤٥٦٧٨٩).
Dla
sort -u
, ① sortuje to samo co ②, a 0123 tak samo jak ٠١٢٣, więcsort -u
zachowa tylko jeden z nich, podczas gdy dlauniq
(nie GNUuniq
, które używastrcoll()
(z wyjątkiem-i
)), ① jest inne od ② i 0123 różni się od ٠١٢٣, więcuniq
uzna wszystkie 4 za unikalne. -
strcoll
moż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 gdystrcmp()
nie ma znaczenia o znakach, ponieważ porównuje tylko bajt do bajtu. To „kolejny powód, dla któregosort -u
może nie zawierać wszystkich unikalnych wierszy, jeśli niektóre z nich nie tworzą prawidłowego tekstu.sort|uniq
, chociaż wciąż nieokreślony w przypadku wprowadzania nietekstowego, w praktyce jest bardziej prawdopodobne, że z tego powodu otrzymasz unikalne linie.
Oprócz tych subtelności, jedna rzecz, której dotychczas nie zauważono, to to, że uniq
porównuje leksykalnie cały wiersz, podczas gdy sort
„s -u
porównuje na podstawie specyfikacji sortowania podanej 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
¹ Wcześniejsze wersje specyfikacji POSIX powodowały jednak zamieszanie, wymieniając zmienną LC_COLLATE
jako zmienną wpływającą na uniq
, która została usunięta w edycji 2018 i zachowanie wyjaśniło się po wspomnianej powyżej dyskusji. Zobacz odpowiedni błąd grupy Austin
² 2019 edytuj . Od tego czasu zostały one naprawione, ale ponad 95% punktów kodowych Unicode nadal ma niezdefiniowaną kolejność w wersji 2.30 biblioteki GNU libc . Zamiast tego możesz przetestować za pomocą 🧙🧚🧛🧜🧝, na przykład w nowszych wersjach
Odpowiedź
Wolę używać sort | uniq
, ponieważ kiedy próbuję użyć opcji -u
(eliminuj duplikaty), aby usunąć duplikaty zawierające ciągi znaków o różnych wielkościach, nie jest to takie łatwe zrozumieć wynik.
Uwaga: zanim uruchomisz poniższe przykłady, musisz zasymulować standardową kolejność zestawiania w 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, jednocześnie zachowując różne przypadki ciągów znakó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 można rozwiązać, nie używając opcji -u
do usuwania duplikatów. Używanie uniq
jest bardziej przewidywalne. Poniższy przykład najpierw sortuje i ignoruje wielkość liter, a następnie przekazuje ją do uniq
w celu usunięcia duplikatów.
$ sort -f short | uniq Apple apple Pear pear
Komentarze
-
-u
opcjasort
wyświetla pierwszy równego przebiegu (patrz strona podręcznika). W ten sposóbsort -fu
wybiera pierwsze wystąpienie każdego unikalnego wiersza bez rozróżniania wielkości liter. Logika, którejsort
używa do usuwania duplikatów, jest przewidywalna.
Odpowiedź
Inną różnicą, którą odkryłem dzisiaj, jest sortowanie na podstawie separatora, w którym sort -u
stosuje unikalną flagę tylko do kolumny, według której 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
Komentarze
- Wspomina o tym odpowiedź św. é phane Chazelas, ale Podoba mi się twój przykład, więc +1
- Dziękuję za wskazanie @roaima, odpowiedź nie była ' bardzo jasna