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 -ubył częścią 7.edycji UNIX, około 1979 roku. Wersjesortbez Obsługa-ujest 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 | uniqw 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 | uniqasort -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 -uzwracatest, aleecho -e 'test \n test' | sort -n | uniqzwraca 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 -unie 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 -uzachowa 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ęcuniquzna wszystkie 4 za 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 gdystrcmp()nie ma znaczenia o znakach, ponieważ porównuje tylko bajt do bajtu. To „kolejny powód, dla któregosort -umoż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
-
-uopcjasortwyświetla pierwszy równego przebiegu (patrz strona podręcznika). W ten sposóbsort -fuwybiera pierwsze wystąpienie każdego unikalnego wiersza bez rozróżniania wielkości liter. Logika, którejsortuż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