Почему сортировка ls игнорирует символы, не являющиеся буквами и цифрами?

Почему сортировка ls игнорирует символы, не являющиеся буквами и цифрами?

При сортировке имен файлов 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

решение1

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. Результат показывает, чтоСпоследовательность идентична исходной сгенерированной последовательности.

{ 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

Это не имеет ничего общего с набором символов. Скорее, это язык, который определяет порядок сортировки. Библиотека libc проверяет язык, представленный в $LC_COLLATE/ $LC_ALL/ $LANG, и ищет его правила сортировки (например, /usr/share/i18n/locales/*для GLibC) и упорядочивает текст в соответствии с указаниями.

решение3

У меня точно такая же проблема с параметрами сортировки Debian по умолчанию. Для меня это запятая, которую система игнорирует, и это мешает мне эффективно сортировать данные CSV, вызывая хаос в моем ИИ.

Решение состоит в том, что вместо использования sort sortпо отдельности мне нужно принудительно вывести sort из поведения по умолчанию, которое, похоже, -d, --dictionary-order.

Выполнение команды:

sort -V

Решает мою проблему и учитывает запятые.

решение4

просто комментарий... у меня большая проблема с моим сопоставлением (es_AR.utf8), потому что я не могу использовать «C» из-за ударений, и хуже всего то, что проблема появляется в базе данных postgresql, также делая то, что предложение между «10» и «10.1» включает (это пример) значение «100», чего я не ожидаю... я думаю, что мне нужно использовать сопоставление в каждом запросе... SELECT '100' BETWEEN '10' AND '10.Z' показывает true, но SELECT '100' BETWEEN '10' AND '10.Z' COLLATE «C» показывает «false», что правильно (на мой взгляд)

Связанный контент