Яка різниця між - загально-числовий-сортування та - числовий-сортування параметри у gnu sort


113

sortнадає два види числового сортування. Це зі сторінки man:

   -g, --general-numeric-sort
          compare according to general numerical value

   -n, --numeric-sort
          compare according to string numerical value

Яка різниця?


17
Зауважте, що повна документація sortне є manсторінкою, а infoсторінкою ( info sort).
a3nm

Відповіді:


85

Загальне числове сортування порівнює числа як плаваючі, це дозволяє наукові позначення, наприклад, 1.234E10, але повільніше і піддається помилці округлення (1.2345678 може прийти після 1.2345679), числове сортування - це лише звичайний алфавітний сорт, який знає, що 10 настає після 9.

Див. Http://www.gnu.org/software/coreutils/manual/html_node/sort-invocation.html

'-g' '- general-numeric-sort' '--sort = general-numeric' Сортування чисельно, використовуючи стандартну функцію strtod C, щоб перетворити префікс кожного рядка в число з плаваючою комою з подвійною точністю. Це дозволяє визначати номери з плаваючою комою в наукових позначеннях, таких як 1.0e-34 та 10e100. Локал LC_NUMERIC визначає символ десяткової крапки. Не повідомляйте про помилки переповнення, переливання чи перетворення. Використовуйте таку послідовність згортання: Рядки, які не починаються з чисел (всі вважаються рівними). NaNs (значення "Не число", в арифметиці з плаваючою точкою IEEE) у послідовному, але залежно від машини порядку. Мінус нескінченності. Кінцеві числа у порядку зростання чисел (при -0 і +0 рівні). Плюс нескінченність.

Використовуйте цей варіант, лише якщо немає альтернативи; він набагато повільніше, ніж - числовий-sort (-n), і він може втрачати інформацію при переході в плаваючу точку.

'-n' '- числовий-сортувати' '--sort = числовий' Сортувати числово. Число починається з кожного рядка і складається з необов'язкових пробілів, необов'язкового знака "-" та нуля чи більше цифр, можливо, розділених тисячами роздільників, необов'язково супроводжуючись символом десяткової крапки та нулем чи більше цифр. Порожнє число трактується як "0". Локал LC_NUMERIC вказує символ десяткової крапки та роздільник тисяч. За замовчуванням порожній - пробіл або вкладка, але локальна локація LC_CTYPE може змінити це.

Порівняння точне; немає помилки округлення.

Ні провідні позначення "+", ні експоненціальні не визнаються. Для порівняння таких рядків чисельно використовуйте параметр --general-numeric-sort (-g).


2
Дякую. Дивно, що на сторінках людини та інформації немає цього. Я також не знав про gnu.org/software/coreutils/manual/html_node/index.html .
Трентон

6
Цей матеріал не працює для мене. Я сортую файл із третього стовпця із вмістом типу R1 R2 R10 R15. Використовуючи або, -k3.2nабо -k3.2g, це сортування R10раніше R2. Сорт лексикографічний, а не числовий. Я очікую, що це поле буде розглядати поле від другого символу і далі як число.
Каз

6
sortОсновні характеристики @Kaz:. є по-справжньому візантійськими - це коротко: порожні (-и), що передують (-ла) поля , вважаються частиною поля , тому знакові. індекс 1 вказує на (перше) поле, що передує полі, а не фактичне перше позначення поля. Суфікс знаку. індекс з, bщоб виправити цю проблему, тобто: -k 3.2bn,3(зауважте, що глобальний -b варіант у цьому випадку не працює). Також зверніть увагу на додане ,3, що гарантує використання лише 3-го поля - без цього 2-го індексу поля використовується решта всього рядка .
mklement0

11

Ви повинні бути обережними зі своїм місцем розташування. Наприклад, ви можете мати намір сортувати плаваюче число (наприклад, 2.2), тоді як ваш локал може очікувати використання коми (наприклад, 2,2).

Як повідомляється на цьому форумі , ви можете мати неправильні результати за допомогою прапорців -n або -g.

У моєму випадку я використовую:

LC_ALL=C sort -k 6,6n file

для сортування 6-го стовпця, який містить:

2.5
3.7
1.4

аби отримати

1.4
2.5
3.7

2
Навіть за допомогою LANG = C я не можу -nрозпізнати кому як роздільник тисяч - "1000" трактується так само, як "1".
Скотт

1
Це має бути LC_ALL = C.
Стюарт П. Бентлі

@Scott: Дійсно, тисячі роздільників НЕ розпізнаються: sortвикористовується логіка найдовшого префікса : використовується найдовша частина рядка / ключа, яку він визнає як число; у локалі, який використовується .як символ радіації, він зупиниться на читанні ,.
mklement0

@ StuartP.Bentley: LC_ALL=Cце справді найбільш надійний вибір; однак, якщо LC_ALLтрапиться не встановити ставку, LANG=Cтеж буде працювати.
mklement0

1
Хороший момент, але LANG=C sort -k 6,6n fileі простіший, а також локалізує ефект встановлення змінної середовища LANGдля конкретної команди.
mklement0

0

На додаток до прийнятої відповіді, в якій згадка -gдозволяє наукові позначення , я хочу показати частину, яка, швидше за все, викликає небажану поведінку.

З -g:

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=en_US.UTF-8 sort -g myfile
baa
--inf
--inf  
--inf- 
--inf--
--inf-a
--nnf
nnf--
   nnn  
tnan
zoo
   naN
Nana
nani lol
-inf
-inf--
-11
-2
-1
1
+1
2
+2
0xa
11
+11
inf

Подивіться тут на zooтри важливі речі:

  • Рядок починається з NAN(наприклад, Nanaі nani lol) або -INF(одиночного тире, не --INF) переміщення до кінця, але перед цифрами. Хоча INFпереходьте до останнього після цифр, оскільки це означає нескінченність .

  • NAN, INFІ -INFце відчутно до регістру .

  • Лінії завжди ігнорують прогалини з обох сторін NAN, INF, -INF (незалежно від LC_CTYPE). Інший алфавіт може ігнорувати пробіли з будь-якої сторони, залежно від місцевості LC_COLLATE(наприклад, LC_COLLATE=fr_FR.UTF-8ігнорувати, але LC_COLLATE=us_EN.UTF-8не ігнорувати).

Отже, якщо ви сортуєте довільну буквено-цифрову, то, ймовірно, не хочете -g. Якщо вам справді потрібне порівняння наукових позначень -g, ви, ймовірно, хочете витягнути алфавітні та числові дані та зробити порівняння окремо .

Якщо вам потрібна лише звичайна 1, -1сортування номерів (наприклад ), і ви вважаєте, що це 0x/E/+ sortingне важливо, просто використовуйте -nдостатньо:

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=en_US.UTF-8 sort -n myfile
-1000
-22
-13
-11
-010
-10
-5
-2
-1
-0.2
-0.12
-0.11
-0.1
0x1
0x11
0xb
+1
+11
+2
-a
-aa
--aa
-aaa
-b
baa
BAA
bbb
+ignore
inf
-inf
--inf
--inf  
--inf- 
--inf--
-inf--
--inf-a
   naN
Nana
nani lol
--nnf
nnf--
   nnn  
None         
uum
Zero cool
-zzz
1
1.1
1.234E10
5
11

Будь-який з -gабо -n, бути в курсі локалі ефекту . Ви можете вказати, LC_NUMERICяк us_EN.UTF-8 уникнути сортування fr_FR.UTF-8 -з помилкою плаваючого числа :

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=fr_FR.UTF-8 sort -n myfile
-10
-5
-2
-1
-1.1
-1.2
-0.1
-0.11
-0.12
-0.2
-a
+b
middle
-wwe
+zoo
1
1.1

З LC_NUMERIC=en_US.UTF-8:

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=en_US.UTF-8 sort -n myfile
-10
-5
-2
-1.2
-1.1
-1
-0.2
-0.12
-0.11
-0.1
-a
+b
middle
-wwe
+zoo
1
1.1

Або LC_NUMERIC=us_EN.UTF-8згрупуватися +|-|spaceз alpha:

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=us_EN.UTF-8 sort -n myfile
-0.1
    a
    b
 a
 b
+b
+zoo
-a
-wwe
middle
1

Можливо, ви хочете вказати localeпід час використання, sortякщо хочете написати портативний сценарій.

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