2014-12-10 6 views
6

Ho un file di testo con le linee di testo UTF-8 codificato:Perché il testo UTF-8 ordina in ordine diverso tra OS X e Linux?

mac-os-x$ cat unsorted.txt 
ウ 
foo 
チ 
'foo' 
津 

In caso aiuta a riprodurre il problema, ecco un checksum e un dump dei byte esatto del file, così come come si potrebbe generare il file da soli (su Linux, utilizzare base64 -d invece di -D):

mac-os-x$ shasum unsorted.txt 
a6d0b708d3e0cafb0c6e1af7450e9243da8cb078 unsorted.txt 

mac-os-x$ perl -ne 'print join(" ", map { sprintf "%02x", ord } split //), "\n"' unsorted.txt 
e3 82 a6 0a 
66 6f 6f 0a 
e3 83 81 0a 
27 66 6f 6f 27 0a 
e6 b4 a5 0a 

mac-os-x$ echo 44KmCmZvbwrjg4EKJ2ZvbycK5rSlCg== | base64 -D > unsorted.txt 

Quando ho risolvere la questione file di input su Mac OS X (indipendentemente dal fatto che io uso GNU ordinamento 5,93 che le navi di Mac OS X Yosemite con, o con una versione di ordinamento GNU installata in Homebrew 8.23), ottengo questo risultato ordinato:

mac-os-x$ env -i LANG=en_US.utf-8 LC_ALL=en_US.utf-8 /usr/bin/sort unsorted.txt 
'foo' 
foo 
ウ 
チ 
津 

mac-os-x$ echo `sw_vers -productName` `sw_vers -productVersion` 
Mac OS X 10.10.1 

mac-os-x$ /usr/bin/sort --version | head -1 
sort (GNU coreutils) 5.93 

Quando sono a ordinare lo stesso file, con le stesse impostazioni locali, su Linux (ho testato su entrambi CentOS 5.5 e CentOS 6.5), ottengo un risultato diverso:

linux-centos-6.5$ env -i LANG=en_US.utf-8 LC_ALL=en_US.utf-8 /bin/sort unsorted.txt 
ウ 
チ 
foo 
'foo' 
津 

linux-centos-6.5$ cat /etc/redhat-release 
CentOS release 6.5 (Final) 

linux-centos-6.5$ /bin/sort --version | head -1 
sort (GNU coreutils) 8.4 

Nota le diverse sedi del giapponese kana contro l'inglese e il diverso ordine tra due linee che differiscono solo dalle virgolette singole.

Per aggiungere un'altra variante al mix, ho notato che su un vecchio FreeBSD 6 scatola che ho, ho lo stesso tipo di ordinamento come OS X:

freebsd-6.0$ env -i LANG=en_US.utf-8 LC_ALL=en_US.utf-8 /usr/bin/sort unsorted.txt 
'foo' 
foo 
ウ 
チ 
津 

freebsd-6.0$ uname -rs 
FreeBSD 6.0-RELEASE 

freebsd-6.0$ sort --version | head -1 
sort (GNU coreutils) 5.3.0-20040812-FreeBSD 

mi aspettavo l'ordinamento di essere il lo stesso in ogni caso, dato che tutti i casi utilizzano l'ordinamento GNU, tutti con le stesse impostazioni locali. Ho provato esplicitamente a impostare LC_COLLATE separatamente e ho provato a utilizzare LC_COLLATE=C per forzare un ordinamento in base all'ordine dei byte, ma questo non ha modificato alcun risultato.

Perché il mio file di input di esempio viene ordinato in modo diverso su OS X e Linux? E come potrei forzare entrambi i sistemi a produrre testo identicamente ordinato (non mi interessa quale variante, purché sia ​​coerente tra i due)?

+1

'LC_ALL' sovrascrive' LC_ * '. https://www.gnu.org/savannah-checkouts/gnu/libc/manual/html_node/Locale-Categories.html –

+1

Sembra che l'impostazione LC_ALL = C faccia corrispondere l'ordine di ordinamento alla variante OS X e FreeBSD su Linux. In modo che risponda alla seconda parte della mia domanda (come potrei forzare entrambi i sistemi a produrre testo identicamente ordinato?). Sto ancora cercando di capire la prima parte della domanda: perché il file di input viene ordinato in modo diverso in un primo momento? Come ha sottolineato @CedricHan, il mio assunto che LC_COLLATE avrebbe vinto su LC_ALL ai fini dell'ordinamento era sbagliato; ma come posso duplicare l'ordinamento Linux sotto OS X? L'ordinamento –

+3

utilizza le tabelle di confronto fornite dal sistema operativo.Se diversi SO forniscono tabelle di confronto diverse, otterrete risultati diversi. Non ha molto senso prevedere un particolare ordine di confronto per script non latini in un locale basato su inglese. 'ja_JP.UTF-8' ha un ordine di confronto diverso da' en_US.UTF-8', che è diverso da 'C'. –

risposta

1

Come sembra - il tuo linux sort non conserva l'ordine UTF-8 corretto.

Hex UTF-8 rappresentazioni dei vostri unsorted.txt (prime lettere) sarebbe:

- 30A6

foo - 0066

- 30C1

'foo' - 0027

- 6D25

tratto da http://www.ltg.ed.ac.uk/~richard/utf-8.cgi?input=%E3%82%A6&mode=char

Così ordinamento corretto in base alle regole di confronto Unicode (http://www.unicode.org/Public/UCA/latest/allkeys.txt) sarebbe:

' foo ' - line 487

foo - linea 8966

- linea 20875

- linea 21004

- non nel file di

Quindi, per rispondere alla tua domanda, la tua macchina Linux fornisce tabelle di confronto errate a sort funzione. Sfortunatamente, non posso dire quale sia la ragione possibile per questo.

PS: C'è una domanda simile alla tua here.

EDIT

Come @ninjalj notato, glibc non usa UCA, ma ISO-14651, invece. This bug report suggeriscono la migrazione all'UCA. Sfortunatamente, non è ancora stato risolto.

Inoltre, potrebbe essere collegato in qualche modo con question about ls case insensivity su MacOSX. Alcune persone suggeriscono addirittura che abbia qualcosa a che fare con il filesystem HFS.

+0

glibc non usa l'UCA, usa ISO-14651. Tra le altre differenze, ISO-14651 non fornisce un ordinamento predefinito per gli elementi di confronto senza pesi definiti nelle tabelle di confronto. – ninjalj

+0

Grazie per avermelo fatto notare, scaverò in quella stasera per modificare la mia risposta. La mia prima cattura sarebbe da qualche parte qui https://sourceware.org/bugzilla/show_bug.cgi?id=14095 –

+0

L'ordine corretto di ordinamento dipende dal locale, non esiste un "ordine UTF-8 corretto". –

Problemi correlati