O que está acontecendo no seguinte snippet de código? Não estou obtendo minha saída esperada.
Eu acho que foi um bug, mas acontece em 2 programas diferentes (uniq e sort), então eu suspeito que isso tenha algo a ver com ... bem, eu não sei o que ... daí a pergunta.
Os 3 primeiros (de 4) exemplos funcionam, mas o 4º falha !.
Eu esperaria o mesmo comportamento para todos e quaisquer personagens.
ie para imprimir 2 linhas (das 3 linhas de entrada) ... mas no 4º caso, recebo apenas 1 linha (para ambos sort -u
e uniq
); os dois lins idênticos simplesmente desaparecem!
Eu converti a saída '\ n' para o espaço para compactar a vista.
Estou usando o uniq e classifico de (GNU coreutils) 7.4 ... executando no Ubuntu 10.04.3 LTS desktop.
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
#
sort
sozinho (sem a opção -u ) ... não devora caracteres. O que entra, sai ... No entanto, como pode ser esperado pela explicação de Gilles dos caracteres unicode "exóticos" que têm o mesmo valor canônico , esses Os caracteres não são classificados, exceto pelo fato de serem emitidos como um grupo FIFO não classificado para o "topo" da saída da classificação ... Portanto, existem realmente dois problemas aqui: 1. Os caracteres não são classificados como podem ser "ingenuamente "esperado e 2. O recurso" exclusivo "de ambossort
euniq
perda de dados (em alguns casos).sort -u
euniq
trabalho bem com:LC_COLLATE=C; echo -e "〼\n〇\n〇" |sort -u
(ou|uniq
)Respostas:
Versão curta: o agrupamento realmente não funciona nos utilitários de linha de comando.
Versão mais longa: a função subjacente para comparar duas strings é
strcoll
. A descrição não é muito útil, mas o método conceitual de operação é converter as duas seqüências de caracteres em uma forma canônica e comparar as duas formas canônicas. A funçãostrxfrm
constrói essa forma canônica.Vamos observar as formas canônicas de algumas strings (com GNU libc, sob o Debian squeeze):
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 intercalação da
en_US.UTF-8
localidade. No entanto, eles estão presentes em um local japonês.O código fonte para os dados de localidade (no squeeze do Debian) está dentro
/usr/share/i18n/locales/en_US
, o que inclui/usr/share/i18n/locales/iso14651_t1_common
. Este arquivo não tem uma entrada paraU3007
ouU303C
, nem está incluído em nenhum intervalo que eu possa encontrar.Não estou familiarizado com as regras para criar a ordem de intercalação , mas, pelo que entendi, o fraseado relevante é
Parece que o Glibc está ignorando caracteres que não foram especificados. Não sei se há uma falha no meu entendimento da especificação POSIX, se perdi alguma coisa na definição de localidade do Glibc ou se há um erro no compilador de localidade Glibc.
fonte
charmaps/UTF-8
não diz nada sobre agrupamento, é olocales/en_US
que importa. A primeira regra deLC_COLLATE
é: não useLC_COLLATE
. No código do idioma C (= POSIX), o agrupamento é razoável (baseado estritamente nos valores de caracteres numéricos).LC_COLLATE=C
... obrigado ...Para "com segurança"
sort
cadeias Unicode, talvez dê uma olhada emmsort
:http://www.billposer.org/Software/msort.html
fonte
msort
. A GUI opcional torna a introdução um pouco mais fácil de entender o que está em oferta. Ser capaz de copiar o comando gerado é muito útil ... E sim, ele classifica os caracteres unicode, mas (você não ama esses "buts":) ...) ... mas não tem uma opção única : (... como mencionado no link que você postou:Capabilities of GNU sort and BSD sort lacking in msort are the ability to merge files without sorting them (the --merge option) and the ability to emit only the first of an equal run (the --unique option)
... o tipo trabalha embora :)