Nie, nie uważa się ich za równoważne, po prostu mają tę samą pierwotną wagę. Tak więc, w pierwszym przybliżeniu, sortują to samo.
Jeśli spojrzysz na / usr / share / i18n / locales / iso14651_t1_common (jako podstawę większości ustawień narodowych) w systemie GNU (tutaj z glibc 2.27), zobaczysz:
<U0065> <e>;<BAS>;<MIN>;IGNORE # 259 e
<U025B> <e>;<PCL>;<MIN>;IGNORE # 287 ɛ
<U0045> <e>;<BAS>;<CAP>;IGNORE # 577 E
e
, ɛ
I E
ma taki sam ciężar podstawowy, e
i E
taki sam ciężar wtórnego tylko trzecia masa odróżnia je.
Podczas porównywania ciągów sort
( strcoll()
standardowa funkcja libc służy do porównywania ciągów) zaczyna się od porównania głównych wag wszystkich znaków i przechodzi na drugą wagę tylko wtedy, gdy ciągi są równe pierwotnym wagom (i tak dalej z innymi wagami) .
W ten sposób wielkość liter wydaje się być ignorowana w kolejności sortowania w pierwszym przybliżeniu. Ab
sortuje pomiędzy aa
i ac
, ale Ab
może sortować przed lub po, w ab
zależności od reguły językowej (niektóre języki miały <MIN>
wcześniej <CAP>
jak w brytyjskim angielskim, niektóre <CAP>
wcześniej <MIN>
jak w estońskim).
Gdyby e
miał taką samą kolejność sortowania jak ɛ
, printf '%s\n' e ɛ | sort -u
zwróciłby tylko jedną linię. Ale jak <BAS>
poprzednio <PCL>
, e
sam sortuje wcześniej ɛ
. eɛe
sortuje po EEE
(według wagi wtórnej), chociaż EEE
sortuje po eee
(dla której musimy przejść do trzeciej wagi).
Teraz, jeśli w moim systemie z glibc 2.27, uruchamiam:
sed -n 's/\(.*;[^[:blank:]]*\).*/\1/p' /usr/share/i18n/locales/iso14651_t1_common |
sort -k2 | uniq -Df1
Zauważysz, że istnieje wiele znaków, które zostały zdefiniowane z dokładnie tymi samymi 4 wagami. W szczególności nasze ɛ ma takie same wagi jak:
<U01DD> <e>;<PCL>;<MIN>;IGNORE
<U0259> <e>;<PCL>;<MIN>;IGNORE
<U025B> <e>;<PCL>;<MIN>;IGNORE
I na pewno:
$ printf '%s\n' $'\u01DD' $'\u0259' $'\u025B' | sort -u
ǝ
$ expr ɛ = ǝ
1
Można to uznać za błąd w ustawieniach narodowych GNU libc. W większości innych systemów ustawienia narodowe zapewniają, że wszystkie znaki mają na końcu inną kolejność sortowania. Na lokalizacjach GNU, robi się jeszcze gorzej, ponieważ istnieją tysiące znaków, które nie mają sortowania i skończyć sortowania samo, powodując różnego rodzaju problemy (jak łamanie comm
, join
, ls
lub globs mających niedeterministycznym zleceń ... ), stąd zalecenie używania w LC_ALL=C
celu obejścia tych problemów .
Jak zauważył @ninjalj w komentarzach, glibc 2.28 wydany w sierpniu 2018 roku przyszedł z pewnymi ulepszeniami na tym froncie, chociaż AFAICS, nadal istnieje kilka znaków lub elementów zestawiających zdefiniowanych w identycznej kolejności sortowania. Na Ubuntu 18.10 z glibc 2.28 oraz w ustawieniach regionalnych en_GB.UTF-8.
$ expr $'L\ub7' = $'L\u387'
1
(dlaczego U + 00B7 miałby być uważany za równoważny jako U + 0387 tylko w połączeniu z L
/ l
?!).
I:
$ 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
(wciąż ponad 1 milion znaków (95% zakresu Unicode, w porównaniu z 98% w 2.27) sortuje się tak samo jak inne znaki, ponieważ ich kolejność sortowania nie jest zdefiniowana).
Zobacz też: