¿Por qué ordena dice que ɛ = e?


25

ɛ("Épsilon latino") es una letra utilizada en ciertos idiomas africanos, generalmente para representar el sonido de la vocal en inglés "bed". En Unicode está codificado como U + 025B, muy distinto de todos los días e.

Sin embargo, si yo sortlo siguiente:

eb
ed
ɛa
ɛc

parece que sortconsidera ɛy eequivalente:

ɛa
eb
ɛc
ed

¿Que está pasando aqui? ¿Y hay una manera de hacer ɛy edistinguir para sortpropósitos?


21
las reglas de clasificación se denominan "colación", si eso ayuda a
buscar en

1
Intente poner una cierta cantidad de eamezcla ɛadentro de un archivo de texto y ordénelo. Verás que siempre se ordena eaantes ɛa. Entonces, no, no se consideran iguales.
Bakuriu

Puede ser un punto obvio, pero aún no lo he visto sugerido explícitamente: si está ordenando palabras en $ (Certain_african_language), lo más natural es establecer la configuración regional en $ (Certain_african_language).
Federico Poloni

@FedericoPoloni Un muy buen punto! Lamentablemente, no he podido encontrar ninguna configuración regional hecha para este idioma.
Draconis

1
@ GermánBouzas Esto es específicamente "épsilon latino", una forma diseñada para encajar con el alfabeto latino. Se ven más o menos iguales, pero el épsilon latino es U + 025B, mientras que el épsilon griego es U + 03B5.
Draconis el

Respuestas:


67

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 Etener el mismo peso primaria, ey Emismo 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. Abclasifica entre aay ac, pero Abpuede ordenar antes o después absegú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 etuviera el mismo orden de clasificación que ɛ, printf '%s\n' e ɛ | sort -usolo devolvería una línea. Pero como <BAS>antes <PCL>, esolo antes ɛ . eɛeclasifica después EEE(en el peso secundario) aunque EEEclasifica 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, lso globos que tienen órdenes de no deterministas ... ), de ahí la recomendación de utilizar LC_ALL=Cpara 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:


3
¡Esto es exactamente lo que estaba buscando! Para completar, ¿qué significa <PCL>? ¿Los otros parecen ser Capital, Minúsculo y Básico?
Draconis

3
@Draconis, símbolo de clasificación <PCL> # 16 particular / peculiar
Stéphane Chazelas

De hecho, si ponemos un montón eay lo ɛamezclamos en un archivo, vemos que sortordena todo eas antes que ɛas.
Bakuriu

2
Desde glibc 2.28, el punto de código debe usarse como respaldo para un peso de 4to nivel, consulte sourceware.org/git/… sourceware.org/bugzilla/show_bug.cgi?id=14095
ninjalj

1
@cat, lo siento, quise decir strcoll(), ver editar.
Stéphane Chazelas

15

tipo de hombre:

   ***  WARNING  ***  The locale specified by the environment affects sort
   order.  Set LC_ALL=C to get the traditional sort order that uses native
   byte values.

Entonces, intente: LC_ALL=C sort file.txt


1
¡Eso funciona! Pero, ¿por qué la configuración regional predeterminada considera que estos puntos de código completamente separados son los mismos? Tengo curiosidad por qué sucede esto.
Draconis

@Draconis ¿Cuál es "la configuración regional predeterminada"?
Kamil Maciorowski

@KamilMaciorowski Un valor vacío de la variable de entorno; No estoy seguro de qué configuración regional corresponde.
Draconis

3
@Draconis si LC_ALLestá vacío, sortpuede usar otras LC_*variables LANGo algunos archivos de configuración.
NieDzejkob

1
LC_COLLATEes el tipo específico de cadena, LANGes el extra general.
ShadowRanger

8

El carácter ɛ no es igual a e, pero algunas localidades pueden juntar estos signos muy cerca al cotejar. La razón de esto es específica del idioma, pero también algunos antecedentes históricos o incluso políticos. Por ejemplo, la mayoría de la gente probablemente espera que la moneda de € uro se acerque a Europa en el diccionario.

De todos modos, para ver qué intercalación está ejecutando actualmente locale, locale -ale dará la lista de configuraciones regionales disponibles en el sistema y para cambiar la intercalación, digamos Csolo para una ejecución de clasificación LC_COLLATE=C sort file. Finalmente para ver cómo las diferentes configuraciones regionales pueden ordenar su archivo, intente

for loc in $(locale -a)
    do echo ____"${loc}"____
    LC_COLLATE="$loc" sort file
done

Canalice el resultado a alguna herramienta de ajuste para elegir la configuración regional que se adapte a sus necesidades.


Esta es una explicación maravillosa, pero los símbolos parecen considerarse idénticos, no solo juntos.
Draconis

1
No, no se consideran idénticos. Agregue una ealínea simple al archivo, luego sort -uobtendrá ambos eay ɛaen la salida. La mejor estrategia frente a cotejar es evitar ( export LC_COLLATE=C). De lo contrario, sucederán muchas cosas feas (por ejemplo, /tmp/[a-z]en bashcoincidirá /tmp/ay /tmp/Ano /tmp/Z).
mosvy

@mosvy Huh, interesante ... ¿entonces se consideran iguales para ordenar pero no para propósitos de unicidad?
Draconis

No se les considera lo mismo. Vea aquí una explicación al respecto.
mosvy

1
@ninjalj, eso puede corregirse en los fnmatch()rangos glibc y regexp, pero no de alguna manera bashimplementa sus rangos por sí mismo usando strcoll(). ksh93 nunca tuvo el problema porque su implementación de rango usa strcoll()y también verifica el caso de los extremos del rango y solo coincide con los caracteres en minúscula si ambos extremos son minúsculas. Los rangos zsh no tienen el problema, ya que se realiza en función del punto de código, no strcoll ().
Stéphane Chazelas
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.