Яка різниця між сортуванням -у та сортуванням uniq ”?


119

Скрізь, де я бачу когось, хто потребує отримання відсортованого, унікального списку, до якого завжди звертаються sort | uniq. Я ніколи не бачив прикладів, де хтось використовує sort -uзамість цього. Чому ні? У чому різниця, і чому для сортування краще використовувати uniq, ніж унікальний прапор?


Відповіді:


119

sort | uniqіснував раніше sort -uі сумісний з більш широким спектром систем, хоча майже всі сучасні системи підтримують -u- це POSIX. Це здебільшого повернення до днів, коли sort -uїх не існувало (і люди не прагнуть змінювати свої методи, якщо спосіб, який вони знають, продовжує працювати, просто подивіться ifconfigпроти ipприйняття).

Ці два, ймовірно, об'єднані, оскільки для видалення дублікатів у файлі потрібна сортування (принаймні, у стандартному випадку), і це надзвичайно поширений випадок використання сортування. Це також швидше внутрішньо, внаслідок можливості одночасно робити обидві операції (і через те, що він не вимагає IPC між uniqі sort). Особливо, якщо файл великий, sort -uшвидше за все , буде використано менше проміжних файлів для сортування даних.

У своїй системі я постійно отримую такі результати:

$ 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

Він також не приховує код повернення sort, який може бути важливим (в сучасних оболонках є способи , щоб отримати це, наприклад, bash«s $PIPESTATUSмасив, але це не завжди вірно).


31
Я схильний використовувати, sort | uniqтому що 9 разів з 10, я насправді трубопроводів uniq -c.
Плутор

5
Зауважимо, що він sort -uбув частиною 7-го видання UNIX, приблизно в 1979 році. Версії sortбез підтримки -uсправді є архаїчними - або написані без уваги до де-факто стандарту перед стандартом POSIX де-юре. Дивіться також Сортування сортування переповнення та uniq у оболонці Linux з 2010 року.
Джонатан Леффлер,

3
+1 через ip. Це 2016 рік і це повідомлення у 2013 році, але про ipкоманду я знаю лише зараз.
dieend

4
+1 за "9 разів з 10, я фактично проводжу uniq -c" (і, можливо, ще один раз для цього sort -nr | head). Мені було цікаво, що еквівалентно sort | uniqVim, коли я дізнався, що Vim має :sort uкоманду. І TIL sort -uіснує також.
Чжуюнь Вей

Зверніть увагу , що є різниця при використанні sort -n | uniqVS. sort -n -u. Наприклад, трейлінг та провідні пробіли будуть сприйматися як копії, sort -n -uале не колишніми! echo -e 'test \n test' | sort -n -uповертає test, але echo -e 'test \n test' | sort -n | uniqповертає обидва рядки.
mxmlnkn

46

Одна відмінність полягає в тому, що uniqє ряд корисних додаткових опцій, таких як пропуск полів для порівняння та підрахунок кількості повторень значення. Прапор sort's -uреалізує лише функціональність команди, що не відзначається uniq.


3
+0,49 для корисної відповіді, але я б сказав, що це щось на кшталт "Вихідні дані sort -uне можна передавати для uniqвикористання деяких корисних параметрів останніх, таких як пропуск полів для порівняння та підрахунок кількості повторень".
l0b0

15
+1 , щоб компенсувати скептик , тому що «немає ніякого способу зробити це безпосередньо з роду» робить відповідь на питання ...
Izkata

42

Що стосується POSIX сумісних sorts і uniqs (GNU uniqв даний час не сумісний у цьому відношенні), є різниця в тому, що sortвикористовується алгоритм згортання локалі для порівняння рядків (як правило, використовується strcoll()для порівняння рядків), при цьому uniqперевіряє ідентичність байтових значень (зазвичай використовується strcmp()) .

Це має значення принаймні з двох причин.

  • У деяких місцевостях, особливо в системах GNU, є різні символи, які сортують однакові. Наприклад, у локалі en_US.UTF-8 в системі GNU всі символи ①②③④⑤⑥⑦⑧⑨⑩ ... та багато інших сортуються однаково, оскільки порядок їх сортування не визначений. Арабські цифри 0123456789 сортуються так само, як і їхні аналогічні індіанці Східної Арабської Республіки (٠١٢٣٤٥٦٧٨٩).

    Бо sort -u① сортує так само, як ② та 0123, те саме, що ٠١٢٣, так sort -uби зберігалося лише одне з кожного, тоді як для uniq(не GNU, uniqякий використовує strcoll()(за винятком -i)), ① відрізняється від ② та 0123 відрізняється від would, тож uniqби врахували всі 4 унікальні.

  • strcollможна порівнювати лише рядки дійсних символів (поведінка не визначена відповідно до POSIX, коли вхід має послідовності байтів, які не утворюють дійсних символів), але strcmp()не хвилює символів, оскільки це лише порівняння байт-байт. Тож це ще одна причина, чому, sort -uможливо, не нададуть всі унікальні рядки, якщо деякі з них не утворюють дійсного тексту. sort|uniq, хоча все ще не визначено для нетекстового введення, на практиці з цієї причини скоріше надати вам унікальні рядки.

Крім цих тонкощів, одна річ , яку не було помічено до сих пір є те , що uniqпорівнює всю лінію лексично, в той час як sort«s -uзіставляються на основі специфікації сортування , заданої в командному рядку.

$ 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

9

Я вважаю за краще використовувати, sort | uniqтому що, коли я намагаюся використовувати -u(усунути дублікати) варіант для видалення дублікатів, що містять змішані рядки регістру, зрозуміти результат не так просто.

Примітка: перед тим, як запустити наведені нижче приклади, вам потрібно змоделювати стандартну послідовність згортання С, виконавши наступне:

LC_ALL=C
export LC_ALL

Наприклад, якщо я хочу сортувати файл та видаляти дублікати, одночасно зберігаючи різні випадки рядків.

$ 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?)

Ця плутанина вирішується не використовуючи -uопцію для видалення дублікатів. Використання uniqбільш передбачуване. Нижче спочатку сортується та ігнорується випадок, а потім передається його uniqдля видалення дублікатів.

$ sort -f short | uniq
Apple
apple
Pear
pear

2
-uопція sortвиводить перший з рівного пробігу (див. сторінку сторінки). Таким чином, sort -fuз'являється перша поява кожної унікальної лінії, нечутливої ​​до конкретних випадків. Логіка, яка sortвикористовується для видалення дублікатів, передбачувана.
pallxk

3

Ще одна відмінність, яку я дізнався сьогодні, - це сортування на основі деліметра, де sort -uзастосовується унікальний прапор лише до стовпця, з яким ви сортуєте.

$ 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

Про це йдеться у відповіді Стефана Шазеласа, але мені подобається ваш приклад, тому +1
roaima

Дякую, що вказали на @roaima, у цій відповіді було не зовсім зрозуміло
Стефанос Чрс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.