Вкажіть порядок сортування за допомогою LC_COLLATE, щоб нижній регістр був перед великими


16

З огляду на файл:

$ cat file
1
a
C
B
2
c
3
A
b

За замовчуванням sortбуде:

$ sort file
1
2
3
a
A
b
B
c
C

З LC_COLLATE=Cтаким чином будете сортувати великі літери перед малі:

$ LC_COLLATE=C sort file
1
2
3
A
B
C
a
b
c

Чи можна зробити сортування, щоб змінити впорядкування регістру, тобто цифри, малі та великі регістри?

Відповіді:


8

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

Переважна більшість локалів не вказує власний порядок сортування, а скопіює порядок сортування, визначений у /usr/share/i18n/locales/iso14651_t1_commonтакому, що саме ви хочете редагувати. Замість того, щоб змінювати порядок сортування майже для кожного локального регіону, змінюючи оригінал iso14651_t1_common, пропоную зробити копію. Деталі про те, як працює порядок сортування та як створити користувальницьку локаль у вашій $HOMEкаталозі без доступу до кореневих файлів, ви знайдете у цій відповіді на подібне запитання .

Ознайомтеся з тим, як aі Aвпорядковуються виходячи з їх записів у iso14651_t1_common:

<U0061> <a>;<BAS>;<MIN>;IGNORE # 198 a
<U0041> <a>;<BAS>;<CAP>;IGNORE # 517 A

bі Bподібні:

<U0062> <b>;<BAS>;<MIN>;IGNORE # 233 b
<U0042> <b>;<BAS>;<CAP>;IGNORE # 550 B

Ми бачимо, що на першому проході обидва aі Aмають символ згортання <a>, а в обох bі Bє символ згортання <b>. Оскільки <a>з'являється раніше <b>в iso14651_t1_common, aі Aпов'язані перед bі B. Другий прохід не розриває зв’язки, оскільки всі чотири символи мають символ згортання <BAS>, але під час третього проходу зв'язки вирішуються, оскільки символ <MIN>рядка для малих літер з’являється у рядку 3467 перед символом згортання великих літер <CAP>(рядок 3488) . Таким чином, порядок сортування закінчується як a, A, b, B.

Заміна першого та третього символів, що складаються, сортує букви спочатку в регістрі (нижній та верхній), потім по наголосу ( <BAS>означає, що не є наголосом), потім за алфавітом. Однак і те, <MIN>і інше <CAP>ставиться до числових цифр, тож це призведе до небажаного ефекту введення цифр після букв.

Найпростіший спосіб зберегти цифри першими, роблячи всі малі літери перед усіма великими літерами, - змусити всі літери зв'язати під час першого порівняння, встановивши їх усі рівні <a>. Щоб переконатися, що вони в алфавітному порядку сортуються за регістром, змініть останній символ згортання IGNOREна поточний перший збірний символ. Дотримуючись цієї закономірності, aстане:

<U0061> <a>;<BAS>;<MIN>;<a> # 198 a

A стане:

<U0041> <a>;<BAS>;<CAP>;<a> # 517 A

b стане:

<U0062> <a>;<BAS>;<MIN>;<b> # 233 b

B стане:

<U0042> <a>;<BAS>;<CAP>;<b> # 550 B

і так далі для решти листів.

Після створення спеціалізованої версії iso14651_t1_commonдотримуйтесь інструкцій у відповіді, зв'язаній вище, щоб скласти власну власну мову.


6

Налаштування LC_COLLATE=Cне завжди достатньо для сортування верхнього регістру перед малим. Можливо, вам доведеться встановити LC_ALL=C.

Це також враховує не буквено-цифрові та навіть недруковані символи, але якщо ви не хочете, щоб були варіанти -dта -i(описано в man sort), вимкніть це.

Це, мабуть, погано вийде з багатобайтового введення, наприклад, UTF-8 з символами, що не належать до ASCII.

Щоб отримати малі літери (по порядку) перед великими літерами (по порядку), найкращим способом, який я можу придумати, що не передбачає виходу повноцінної мови програмування, - це перевернення регістру всіх букв перед сортуванням та перевернення їх назад згодом.

tr 'a-zA-Z' 'A-Za-z' < file | LC_ALL=C sort | tr 'a-zA-Z' 'A-Za-z'

2

Я не експерт, але я ніколи не бачив локалі, який визначав би таке порівняння. AFAIK це порівняння є лише в C, де воно засноване на значеннях ASCII . (Зазвичай я би просто вирішив це за сценарієм.)

Однак я ніколи цього не робив, але ви, можливо, захочете поглянути на вказівки щодо localedef (1) та locale (5), щоб зрозуміти, як визначаються локалі та врешті визначити ваш власний.

Також не забувайте, що якщо є якісь діакритики або спеціальні символи, мова C не буде ставитися до них так, як ви цього хочете. Наприклад, він не буде розміщений áпоблизу aчи Łпоблизу L. У таких випадках рідна мова мови могла б бути кращою відправною точкою.


0

Я вважаю, що відповідь не потребує зміни LC_COLLATE (маючи на увазі залишення функції як поведінку за замовчуванням):

сортувати -f файл

Це працює в Linux; будь ласка, зверніться до розділу довідки щодо команди, якщо ви перебуваєте на Unix та працюєте в іншій версії. -f визначається як ігнорування випадку.

Дякуємо за досить (і як не дивно) швидке виправлення та редагування в неправильній граматиці Стівена Рауха.


-1
LC_COLLATE="en_US.UTF-8" sort file

Це не сортувати малі регістри перед великими літерами? ideone.com/Gtyg4Z
iiSeymour

Хм, у моєму випадку це було зроблено за вашим прикладом.
unxnut

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