Нет, он не считает их эквивалентными, они просто имеют одинаковый основной вес. Так что в первом приближении они сортируются одинаково.
Если вы посмотрите на / usr / share / i18n / locales / iso14651_t1_common (который используется в качестве основы для большинства локалей) в системе GNU (здесь с glibc 2.27), вы увидите:
<U0065> <e>;<BAS>;<MIN>;IGNORE # 259 e
<U025B> <e>;<PCL>;<MIN>;IGNORE # 287 ɛ
<U0045> <e>;<BAS>;<CAP>;IGNORE # 577 E
e
, ɛ
И E
имеют тот же первичный вес, e
и тот E
же вторичный вес, только третий вес отличает их.
При сравнении строк sort
( strcoll()
стандартная функция libc используется для сравнения строк) начинается с сравнения первичных весов всех символов и идет только для второго веса, если строки равны первичным весам (и т. Д. С другими весами) ,
Вот как случай, кажется, игнорируется в порядке сортировки в первом приближении. Ab
сортирует между aa
и ac
, но Ab
может сортировать до или после, в ab
зависимости от языкового правила (некоторые языки <MIN>
до этого, <CAP>
как в британском английском, некоторые <CAP>
до <MIN>
как на эстонском).
Если бы e
имел тот же порядок сортировки ɛ
, printf '%s\n' e ɛ | sort -u
что, вернул бы только одну строку. Но, как и <BAS>
раньше <PCL>
, e
одни только раньше ɛ
. eɛe
сортирует после EEE
(при вторичном весе), хотя EEE
сортирует после eee
(для которого нам нужно подняться до третьего веса).
Теперь, если в моей системе с glibc 2.27, я запускаю:
sed -n 's/\(.*;[^[:blank:]]*\).*/\1/p' /usr/share/i18n/locales/iso14651_t1_common |
sort -k2 | uniq -Df1
Вы заметите, что есть довольно много символов, которые были определены с одинаковыми 4 весами. В частности, наш ɛ имеет тот же вес, что и:
<U01DD> <e>;<PCL>;<MIN>;IGNORE
<U0259> <e>;<PCL>;<MIN>;IGNORE
<U025B> <e>;<PCL>;<MIN>;IGNORE
И конечно же:
$ printf '%s\n' $'\u01DD' $'\u0259' $'\u025B' | sort -u
ǝ
$ expr ɛ = ǝ
1
Это можно рассматривать как ошибку в GNU libc locales. В большинстве других систем локали гарантируют, что все разные символы имеют разный порядок сортировки в конце. На GNU локалей, это становится еще хуже, так как есть тысячи символов , которые не имеют порядка сортировки и в конечном итоге сортировки же, в результате чего всех видов проблем (например , разбивающиеся comm
, join
, ls
или комки , имеющих недетерминированные заказы ... ), следовательно, рекомендуется использовать LC_ALL=C
для решения этих проблем .
Как отметил @ninjalj в комментариях, в версии glibc 2.28, выпущенной в августе 2018 года, были некоторые улучшения в этом направлении, хотя в AFAICS все еще есть некоторые символы или элементы сопоставления, определенные с одинаковым порядком сортировки. В Ubuntu 18.10 с glibc 2.28 и в локали en_GB.UTF-8.
$ expr $'L\ub7' = $'L\u387'
1
(почему U + 00B7 считается эквивалентным U + 0387 только в сочетании с L
/ l
?!).
А также:
$ perl -lC -e 'for($i=0; $i<0x110000; $i++) {$i = 0xe000 if $i == 0xd800; print chr($i)}' | sort > all-chars-sorted
$ uniq -d all-chars-sorted | wc -l
4
$ uniq -D all-chars-sorted | wc -l
1061355
(по-прежнему более 1 миллиона символов (95% диапазона Unicode, по сравнению с 98% в 2.27), сортировка аналогична другим символам, поскольку порядок их сортировки не определен).
Смотрите также: