Чому ls сортування ігнорує не буквено-цифрові символи?


25

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

Приклад:

touch a1 a2 a-1 a-2 a_1 a_2 a.1 a.2 a,1 a,2

Тепер покажіть ці файли за допомогою ls -1:

a1
a_1
a-1
a,1
a.1
a2
a_2
a-2
a,2
a.2

Я очікував приблизно такого:

a1
a2
a,1
a,2
a.1
a.2
a_1
a_2
a-1
a-2

тобто я очікував, що не алфавітно-цифрові символи будуть враховані при сортуванні.

Хтось може пояснити таку поведінку? Чи така поведінка зобов'язана стандартом? Або це пов’язано з кодуванням UTF-8?

Оновлення: Схоже, це пов’язано з сортуванням UTF-8:

$ LC_COLLATE=C ls -1
a,1
a,2
a-1
a-2
a.1
a.2
a1
a2
a_1
a_2

2
UTF-8 та ASCII ідентичні, якщо ви використовуєте лише перші 128 кодових точок (що є вашим прикладом). Що станеться, якщо ти зробиш LC_COLLATE=C ls?
Олексій

Проблема не в тому, що ASCII і UTF-8 є ідентичними, це швидше, що UTF-8 має власні правила зіставлення (сортування).
Даніель Куллман

1
Так, це правда, [_-,.]що групуються і якось напів ігноруються. Я не знаю точно, як і де визначено таке зіставлення, але це повинно бути питанням порівняння, тому що просто, і лише зміна порівняння на C (через LC_COLLATE=C ls -l) достатньо, щоб надати порядку сортування, який ви очікували (якщо вважати, що LC_ALLце не перевищує LC_COLLATE). Це справедливо для всього діапазону символів у багатомовній площині Unicode Basic ... Я відредагував свою відповідь, щоб включити приклад сценарію, який це підтверджує ...
Peter.O

якщо вам не подобається, як він працює, ви можете створити псевдонім і помістити його у ~ / .profile: alias ls = 'LC_COLLATE = C ls' </kbd>
jippie

Відповіді:


10

Це не має нічого спільного з гардеробом. Швидше, саме мова визначає порядок порівняння. Libc вивчає мову, представлену в $LC_COLLATE/ $LC_ALL/, $LANGі шукає правила його зіставлення (наприклад, /usr/share/i18n/locales/*для GLibC) і замовляє текст за вказівкою.


FYI: Це складніше, ніж це. Якби strcollнаприклад, наприклад, ви побачили, що щось подібне aasa.cбуло б відсортовано вище aas.c.
Дон Скотт

12

EDIT: Додано тест для даних, відсортованих за LC_COLLATE = C


Послідовність порівняння за замовчуванням трактує ці символи типу "пунктуація" як однакові значення. Use LC_COLLATE=CОбробляти їх у порядку кодової точки ..

for i in 'a1' 'a_1' 'a-1' 'a,1' 'a.1' 'a2' 'a_2' 'a-2' 'a,2' 'a.2' ;do
  echo $i; 
done |LC_COLLATE=C sort

Вихідні дані

a,1
a,2
a-1
a-2
a.1
a.2
a1
a2
a_1
a_2

Наступний код перевіряє всі дійсні символи UTF-8 у базовій багатомовній площині (за винятком \ x00 та \ x0a ; для простоти).
Він порівнює файл у відомій (згенерованій) висхідній послідовності, з цим файлом, випадковим чином відсортованим, а потім знову відсортованим із LC_COLLATE = C. Результат показує, що послідовність C ідентична початковій генерованій послідовності.

{ i=0 j=0 k=0 l=0
  for i in {0..9} {A..F} ;do
  for j in {0..9} {A..F} ;do
  for k in {0..9} {A..F} ;do
  for l in {0..9} {A..F} ;do
     (( 16#$i$j$k$l == 16#0000 )) && { printf '.' >&2; continue; }
     (( 16#$i$j$k$l == 16#000A )) && { printf '.' >&2; continue; }
     (( 16#$i$j$k$l >= 16#D800    && 
        16#$i$j$k$l <= 16#DFFF )) && { printf '.' >&2; continue; }
     (( 16#$i$j$k$l >= 16#FFFE )) && { printf '.' >&2; continue; }
     echo 0x"$i$j$k$l" |recode UTF-16BE/x4..UTF-8 || { echo "ERROR at codepoint $i$j$k$l " >&2; continue; } 
     echo 
  done
  done
  done; echo -n "$i$j$k$l " >&2
  done; echo >&2
} >listGen

             sort -R listGen    > listRandom
LC_COLLATE=C sort    listRandom > listCsort 

diff <(cat listGen;   echo "last line of listOrig " ) \
     <(cat listCsort; echo "last line of listCsort" )
echo 
cmp listGen listCsort; echo 'cmp $?='$?

Вихід:

63485c63485
< last line of listOrig 
---
> last line of listCsort

cmp $?=0

2
Де це задокументовано? Це частина стандарту Unicode?
Даніель Куллман

2
Насправді вони не отримують однакової цінності; ці символи просто ігноруються при сортуванні. Якби вони розглядалися як однакові за значенням, порядок сортування a_1 a2 a_2був би неможливим.
daniel kullmann

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