Perché l'ordinamento dice che ɛ = e?


25

ɛ("Epsilon latino") è una lettera usata in alcune lingue africane, di solito per rappresentare il suono vocale nella "base" inglese. In Unicode è codificato come U + 025B, molto distinto da tutti i giorni e.

Tuttavia, se io sortil seguente:

eb
ed
ɛa
ɛc

sembra che sortconsideri ɛed eequivalenti:

ɛa
eb
ɛc
ed

Cosa sta succedendo qui? E c'è un modo di fare ɛe edistinguere per sortscopi?


21
le regole di ordinamento sono chiamate 'collation', se questo aiuta il tuo googling
BlueRaja - Danny Pflughoeft

1
Prova a mettere un certo numero di eamescolati con ɛadentro un file di testo e ordinalo. Vedrai che ordina sempre eaprima ɛa. Quindi, no, non sono considerati uguali.
Bakuriu,

Potrebbe essere un punto ovvio, ma non l'ho ancora visto suggerito in modo esplicito: se stai ordinando le parole in $ (certain_african_language), la cosa naturale da fare è impostare le impostazioni locali su $ (certain_african_language).
Federico Poloni,

@FedericoPoloni Un ottimo punto! Sfortunatamente non sono stato in grado di trovare impostazioni locali per questa lingua.
Draconis,

1
@ GermánBouzas Questo è specificamente "epsilon latino", una forma progettata per adattarsi all'alfabeto latino. Sembrano praticamente uguali, ma epsilon latino è U + 025B, mentre epsilon greco è U + 03B5.
Draconis,

Risposte:


67

No, non li considera equivalenti, hanno solo lo stesso peso primario. In modo che, in prima approssimazione, ordinino lo stesso.

Se guardi / usr / share / i18n / locales / iso14651_t1_common (usato come base per la maggior parte delle versioni locali) su un sistema GNU (qui con glibc 2.27), vedrai:

<U0065> <e>;<BAS>;<MIN>;IGNORE # 259 e
<U025B> <e>;<PCL>;<MIN>;IGNORE # 287 ɛ
<U0045> <e>;<BAS>;<CAP>;IGNORE # 577 E

e, ɛE Ehanno lo stesso peso primario, ee Elo stesso peso secondario, solo il terzo peso li differenzia.

Quando si confrontano le stringhe, sort(la strcoll()funzione libc standard viene utilizzata per confrontare le stringhe) inizia confrontando i pesi primari di tutti i caratteri e si procede al secondo peso solo se le stringhe sono uguali ai pesi primari (e così via con gli altri pesi) .

Ecco come il caso sembra essere ignorato nell'ordinamento in prima approssimazione. Abordina tra aae ac, ma Abpuò ordinare prima o dopo a abseconda della regola della lingua (alcune lingue hanno <MIN>prima <CAP>come nell'inglese britannico, altre <CAP>prima <MIN>come nell'estone).

Se eavesse lo stesso ordinamento di ɛ, printf '%s\n' e ɛ | sort -urestituirebbe solo una riga. Ma come <BAS>prima <PCL>, esolo prima ɛ . eɛeordina dopo EEE(al peso secondario) anche se EEEordina dopo eee(per il quale dobbiamo salire al terzo peso).

Ora se sul mio sistema con glibc 2.27, corro:

sed -n 's/\(.*;[^[:blank:]]*\).*/\1/p' /usr/share/i18n/locales/iso14651_t1_common |
  sort -k2 | uniq -Df1

Noterai che ci sono alcuni personaggi che sono stati definiti con gli stessi 4 pesi esatti. In particolare, il nostro ɛ ha gli stessi pesi di:

<U01DD> <e>;<PCL>;<MIN>;IGNORE
<U0259> <e>;<PCL>;<MIN>;IGNORE
<U025B> <e>;<PCL>;<MIN>;IGNORE

E abbastanza sicuro:

$ printf '%s\n' $'\u01DD' $'\u0259' $'\u025B' | sort -u
ǝ
$ expr ɛ = ǝ
1

Questo può essere visto come un bug di GNU libc locales. Sulla maggior parte degli altri sistemi, le impostazioni locali assicurano che tutti i diversi caratteri abbiano un diverso ordinamento alla fine. Sul locali GNU, diventa ancora peggio, in quanto vi sono migliaia di caratteri che non dispongono di un ordinamento e finiscono per l'ordinamento stesso, causando problemi di ogni genere (come rottura comm, join, lso gocce con gli ordini non deterministici ... ), quindi la raccomandazione di utilizzare LC_ALL=Cper aggirare tali problemi .

Come notato da @ninjalj nei commenti, glibc 2.28 rilasciato nell'agosto 2018 è arrivato con alcuni miglioramenti su questo fronte sebbene AFAICS, ci siano ancora alcuni personaggi o elementi di fascicolazione definiti con lo stesso ordinamento. Su Ubuntu 18.10 con glibc 2.28 e in una locale en_GB.UTF-8.

$ expr $'L\ub7' = $'L\u387'
1

(perché U + 00B7 sarebbe considerato equivalente a U + 0387 solo se combinato con L/ l?!).

E:

$ 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

(ancora oltre 1 milione di caratteri (95% dell'intervallo Unicode, in calo dal 98% in 2,27) ordinamento uguale agli altri caratteri in quanto il loro ordine di ordinamento non è definito).

Guarda anche:


3
Questo e 'esattamente quello che stavo cercando! Per completezza, cosa significa <PCL>? Gli altri sembrano essere Capital, Miniscule e Basic?
Draconis,

3
@Draconis, collating -symbol <PCL> # 16 particulier / peculiar
Stéphane Chazelas,

In effetti, se mettiamo insieme eae ɛamescoliamo insieme in un file, vediamo che sorttutti eai tipi prima di ɛas.
Bakuriu,

2
Da glibc 2.28, il punto di codice dovrebbe essere usato come fallback per un peso di 4 ° livello, vedi sourceware.org/git/… sourceware.org/bugzilla/show_bug.cgi?id=14095
ninjalj

1
@cat, scusa, volevo dire strcoll(), vedi modifica.
Stéphane Chazelas,

15

ordinamento uomo:

   ***  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.

Allora prova: LC_ALL=C sort file.txt


1
Che funzioni! Ma perché le impostazioni internazionali predefinite considerano questi punti di codice completamente separati uguali? Sono curioso di sapere perché questo accada.
Draconis,

@Draconis Che cos'è "la locale predefinita"?
Kamil Maciorowski il

@KamilMaciorowski Un valore vuoto della variabile d'ambiente; Non sono sicuro a quale locale corrisponde.
Draconis,

3
@Draconis se LC_ALLè vuoto, sortpuò utilizzare altre LC_*variabili LANGo alcuni file di configurazione.
NieDzejkob,

1
LC_COLLATEè quello specifico per l'ordinamento delle stringhe, LANGè quello extra generale.
ShadowRanger,

8

Il carattere ɛ non è uguale a e, ma alcuni locali possono raggruppare questi segni ravvicinati al momento del confronto. La ragione di ciò è specifica della lingua, ma anche un retroscena storico o politico. Ad esempio, molte persone probabilmente si aspettano che la valuta € uro si avvicini all'Europa nel dizionario.

Ad ogni modo, per vedere quali regole di confronto si stanno utilizzando locale, locale -averrà visualizzato l'elenco delle impostazioni locali disponibili sul sistema e, per modificare le regole di confronto, dire Csolo per una sequenza di ordinamento LC_COLLATE=C sort file. Infine, per vedere come diverse versioni locali possono ordinare il tuo file, prova

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

Inoltra il risultato a uno strumento greping per scegliere le impostazioni internazionali più adatte alle tue esigenze.


Questa è una spiegazione meravigliosa, ma i simboli sembrano essere considerati identici, non solo vicini.
Draconis,

1
No, non sono considerati identici. Aggiungi una ealinea semplice al file, quindi con sort -ute otterrai entrambi eae ɛanell'output. La migliore strategia vs. fascicolazione è evitare ( export LC_COLLATE=C). Altrimenti, accadranno molte cose brutte (es. /tmp/[a-z]In bashcorrisponderanno /tmp/ae /tmp/Ama non /tmp/Z).
mosvy,

@mosvy Huh, interessante ... quindi sono considerati uguali per scopi di ordinazione ma non per unicità?
Draconis,

non sono considerati uguali. vedi qui una spiegazione al riguardo.
mosvy,

1
@ninjalj, che può essere risolto negli fnmatch()intervalli glibc e regexp, ma non in alcuni come bashquelli implementano i suoi intervalli da solo usando strcoll(). ksh93 non ha mai avuto il problema perché la sua implementazione di range usa strcoll()e controlla anche il caso di end di intervallo e corrisponde solo a caratteri minuscoli se entrambe le estremità sono minuscole. Gli intervalli zsh non presentano il problema poiché è basato sul punto di codice, non su strcoll ().
Stéphane Chazelas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.