Сортувати не сортуючи лінії за допомогою труби '|' в ньому правильно


17

Я намагаюся відсортувати деякі прості дані, обмежені трубою. Однак сортування насправді не сортування. Він переміщує мій рядок заголовка донизу, але два мої ряди, починаючи з 241, розділяються на рядок, починаючи з 24.

cat sort_fail.csv
column_a|column_b|column_c
241|212|20810378
24|121|2810172
241|213|20810376

sort sort_fail.csv
241|212|20810378
24|121|2810172
241|213|20810376
column_a|column_b|column_c

Заголовки стовпців переміщуються до нижньої частини файлу, тому сортування чітко обробляє його. Але фактичні значення не сортуються так, як я очікував.

У цьому випадку я працював над цим

sort sort_fail.csv --field-separator='|' -k1,1

Але я відчуваю, що це не повинно бути необхідним. Чому сортування не сортується?


2
використання LC_COLLATE=C sort. Залежно від того, що ви очікуєте, вам також може знадобитисяLC_COLLATE=C sort -t'|' -n
mosvy

3
Для сортування даних типу "csv style", які ви можете використовувати csvsortз csvkit, які належним чином обробляють цитовані значення.
Бакуріу

Відповіді:


32

sort відомо про місцеві мови, тому залежно від налаштувань LC_COLLATE (які успадковані від LANG), ви можете отримати різні результати:

$ LANG=C sort sort_fail.csv 
241|212|20810378
241|213|20810376
24|121|2810172
column_a|column_b|column_c

$ LANG=en_US sort sort_fail.csv
241|212|20810378
24|121|2810172
241|213|20810376
column_a|column_b|column_c

Це може спричинити проблеми в сценаріях, оскільки ви, можливо, не знаєте про те, для чого встановлено мову виклику, і тому ви можете отримати різні результати.

Не рідкість сценаріїв, щоб змусити потрібні налаштування

напр

$ grep 'LC.*sort' /bin/precat
      LC_COLLATE=C sort -u | prezip-bin -z "$cmd: $2"

Тепер, що тут цікаво, це |персонаж виглядає дивно.

Але це тому, що каже правило за замовчуванням для en_US, яке походить від ISO

$ grep 007C /usr/share/i18n/locales/iso14651_t1_common
<U007C> IGNORE;IGNORE;IGNORE;<j> # 142 |

Що означає, що |персонаж ігнорується, і порядок сортування буде таким, як якщо б його не було.

$ tr -d '|' < sort_fail.csv | LANG=C sort
24121220810378
241212810172
24121320810376
column_acolumn_bcolumn_c

І це відповідає "несподіваному" сортування, яке ви бачите.

Робочі напрямки полягають у використанні -n(примусові числові сортування) або в розділенні поля (як ви це робили) або у використанні Cлокалі.


Захоплююче. Я бачив деякі інші звернення щодо локалізації, але подумав, що це вплине на відносне впорядкування 24 проти 241, а не щось подібне.
user10777668

7
щось додаткове корисне в GNU сортуванні - це --debugпараметр, який вказує ключ (підкреслений), який використовується для порівняння
Jeff Schaller

запуск з --debug просто підкреслює всю лінію - сортування включає характер труби, він просто встановлений, щоб не мати впливу через локалізацію. Це хороша функція, але не допомогла мені в цьому випадку (я спробував :)
user10777668

Саме тому я згадав про це, @ user10777668 - це вказує на те, що sortвикористовується весь рядок, а не зупиняється на символах, які ми вважаємо, що це є.
Джефф Шаллер

Я не очікував, що це припиниться. Я очікував, що він розпізнає характер труби і включить її до сорту, тому трактуючи 24 | 1 і 241 по-різному. Я не впевнений, як --debug змінив би це, і насправді, враховуючи, що він підкреслює | здається, він би активно відволікся від реальної проблеми, коли локалізація призвела до того, що характер труби було
інгіговано

1

Що мене дратує, це те, що 24він не рухається зі свого місця між двома 241. Друге поле починається з а 1. При спробі сортування з ведучим 4у другому полі, the 24переміщується вниз, тому я підозрюю, що sortпросто ігнорує, |якщо не сказано інше. Спробуйте sort -n...


1

-n, - числове порівняння порівняння відповідно до числового значення рядка

210
23

Без -n, 210 за текстом випереджає 23, оскільки це відповідає моєму персонажу.


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