No, no los considera equivalentes, solo tienen el mismo peso primario. Para que, en primera aproximación, clasifiquen lo mismo.
Si observa / usr / share / i18n / locales / iso14651_t1_common (como se usa como base para la mayoría de las configuraciones regionales) en un sistema GNU (aquí con glibc 2.27), verá:
<U0065> <e>;<BAS>;<MIN>;IGNORE # 259 e
<U025B> <e>;<PCL>;<MIN>;IGNORE # 287 ɛ
<U0045> <e>;<BAS>;<CAP>;IGNORE # 577 E
e
, ɛ
Y E
tener el mismo peso primaria, e
y E
mismo peso secundaria, sólo el tercero de peso que los diferencia.
Al comparar cadenas, sort
(la strcoll()
función libc estándar se usa para comparar cadenas) comienza comparando los pesos primarios de todos los caracteres, y solo pasa al segundo peso si las cadenas son iguales a los pesos primarios (y así sucesivamente con los otros pesos) .
Así es como se ignora el caso en el orden de clasificación en primera aproximación. Ab
clasifica entre aa
y ac
, pero Ab
puede ordenar antes o después ab
según la regla del idioma (algunos idiomas tienen <MIN>
antes, <CAP>
como en inglés británico, otros <CAP>
antes, <MIN>
como en estonio).
Si e
tuviera el mismo orden de clasificación que ɛ
, printf '%s\n' e ɛ | sort -u
solo devolvería una línea. Pero como <BAS>
antes <PCL>
, e
solo antes ɛ
. eɛe
clasifica después EEE
(en el peso secundario) aunque EEE
clasifica después eee
(para lo cual necesitamos subir al tercer peso).
Ahora si en mi sistema con glibc 2.27, ejecuto:
sed -n 's/\(.*;[^[:blank:]]*\).*/\1/p' /usr/share/i18n/locales/iso14651_t1_common |
sort -k2 | uniq -Df1
Notarás que hay bastantes caracteres que se han definido con exactamente los mismos 4 pesos. En particular, nuestro ɛ tiene los mismos pesos que:
<U01DD> <e>;<PCL>;<MIN>;IGNORE
<U0259> <e>;<PCL>;<MIN>;IGNORE
<U025B> <e>;<PCL>;<MIN>;IGNORE
Y efectivamente:
$ printf '%s\n' $'\u01DD' $'\u0259' $'\u025B' | sort -u
ǝ
$ expr ɛ = ǝ
1
Eso puede verse como un error de las configuraciones regionales de GNU libc. En la mayoría de los otros sistemas, las configuraciones regionales se aseguran de que todos los caracteres tengan un orden de clasificación diferente al final. En lugares de GNU, lo que es aún peor, ya que hay miles de caracteres que no tienen un orden de clasificación y terminan la clasificación de la misma, causando todo tipo de problemas (como romper comm
, join
, ls
o globos que tienen órdenes de no deterministas ... ), de ahí la recomendación de utilizar LC_ALL=C
para solucionar esos problemas .
Como señaló @ninjalj en los comentarios, glibc 2.28 lanzado en agosto de 2018 trajo algunas mejoras en ese frente, aunque AFAICS, todavía hay algunos caracteres o elementos de clasificación definidos en un orden de clasificación idéntico. En Ubuntu 18.10 con glibc 2.28 y en un entorno local en_GB.UTF-8.
$ expr $'L\ub7' = $'L\u387'
1
(¿por qué U + 00B7 se consideraría equivalente a U + 0387 solo cuando se combina con L
/ l
?!).
Y:
$ 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
(todavía más de 1 millón de caracteres (95% del rango Unicode, por debajo del 98% en 2.27) ordenando lo mismo que otros caracteres ya que su orden de clasificación no está definido).
Ver también: