Onde foi minha linha 'uniq' ou 'sort -u', com alguns caracteres unicode

8

O que está acontecendo no seguinte trecho de código? Eu não estou recebendo minha saída esperada.

Eu acho que foi um bug, mas isso acontece por 2 programas diferentes (uniq e sort), então eu suspeito que é algo a ver com ... bem, eu não sei o que .. daí a questão .

Os primeiros 3 (de 4) exemplos funcionam, mas o 4º falhará !.

Eu esperaria o mesmo comportamento para todos e quaisquer caracteres.
ie. para imprimir 2 linhas (das 3 linhas de entrada) ... mas no 4º caso, eu só obtenho 1 linha (para sort -u e uniq ); os dois lins idênticos simplesmente desaparecem!

Eu converti a saída '\ n' para o espaço para compacidade de exibição.

Estou usando o uniq e classificando de (GNU coreutils) 7.4 ... rodando na área de trabalho do Ubuntu 10.04.3 LTS.

O script:

{
  locale -k LC_COLLATE
  echo
  for c1 in x 〼 ;do 
    for c2 in z 〇 ;do 
      echo -n "asis   : "; echo -e "$c1\n$c2\n$c2"          |tr '\n' ' ';echo
      echo -n "uniq   : "; echo -e "$c1\n$c2\n$c2" |uniq    |tr '\n' ' ';echo
      echo -n "sort -u: "; echo -e "$c1\n$c2\n$c2" |sort -u |tr '\n' ' ';echo
      echo
    done
    echo
  done
}

A saída:

collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=2081
collate-codeset="UTF-8"

asis   : x z z 
uniq   : x z 
sort -u: x z 

asis   : x 〇 〇 
uniq   : x 〇 
sort -u: 〇 x 


asis   : 〼 z z 
uniq   : 〼 z 
sort -u: 〼 z 

asis   : 〼 〇 〇 
uniq   : 〼 
sort -u: 〼 

# In the last example (of 4) where did the '〇' go? .. U+3007 IDEOGRAPHIC NUMBER ZERO
#
    
por Peter.O 22.07.2011 / 07:23

2 respostas

10

Versão resumida: o agrupamento realmente não funciona nos utilitários de linha de comando.

Versão mais longa: a função subjacente para comparar duas sequências é strcoll . A descrição não é muito útil, mas o método conceitual de operação é converter as duas cadeias em uma forma canônica e, em seguida, comparar as duas formas canônicas. A função strxfrm constrói essa forma canônica.

Vamos observar as formas canônicas de algumas strings (com o GNU libc, sob o Debian squeeze):

$ export LC_ALL=en_US.UTF-8
$ perl -C255 -MPOSIX -le 'print "$_ ", unpack("h*", strxfrm($_)) foreach @ARGV' b a A à 〼 〇
b d010801020
a c010801020
A c010801090
à 101010102c6b
〼 101010102c6b102c6b102c6b
〇 101010102c6b102c6b102c6b

Como você pode ver, 〼 e 〇 têm a mesma forma canônica. Eu acho que é porque esses caracteres não são mencionados nas tabelas de agrupamento do en_US.UTF-8 locale. Eles estão, no entanto, presentes em uma localidade japonesa.

$ export LC_ALL=ja_JP.UTF-8
$ perl -C255 -MPOSIX -le 'print "$_ ", unpack("h*", strxfrm($_)) foreach @ARGV' 〼 〇 
〼 303030
〇 3c9b

O código-fonte dos dados do código do idioma (em squeeze Debian) está em /usr/share/i18n/locales/en_US , que inclui /usr/share/i18n/locales/iso14651_t1_common . Este arquivo não tem uma entrada para U3007 ou U303C , nem estão incluídos em nenhum intervalo que eu possa encontrar.

Não estou familiarizado com as regras para criar a ordem de agrupamento , mas pelo que entendi, o fraseado relevante é

The symbol UNDEFINED shall be interpreted as including all coded character set values not specified explicitly or via the ellipsis symbol. (…) If no UNDEFINED symbol is specified, and the current coded character set contains characters not specified in this section, the utility shall issue a warning message and place such characters at the end of the character collation order.

Parece que o Glibc está ignorando caracteres que não estão especificados. Eu não sei se há uma falha no meu entendimento da especificação POSIX, se eu perdi alguma coisa na definição de código de idioma do Glibc, ou se há um bug no compilador de código de idioma do Glibc.

    
por 22.07.2011 / 17:44
6

Para "com segurança" sort cadeias de caracteres Unicode, talvez dê uma olhada em msort :

[...] Msort provides greater flexibility in selecting key fields, more comparison types, the ability to use collation rules from different locales on different keys, the ability to handle numbers in non-Western number systems, and a variety of other options lacking in GNU sort and BSD sort. Whereas msort understands Unicode, GNU sort and BSD sort do not. [...]

link

    
por 22.07.2011 / 21:29