Qual é o C
valor para LC_ALL
sistemas Unix?
Eu sei que ele força o mesmo local para todos os aspectos, mas o que C
faz?
environment-variables
locale
jcubic
fonte
fonte
xclock
aviso (Missing charsets in String to FontSet conversion
), será melhor usar issoLC_ALL=C.UTF-8
para evitar problemas com o cirílico. Para definir essa variável de ambiente, você deve adicionar a seguinte linha ao final do~/.bashrc
arquivo -export LC_ALL=C.UTF-8
Respostas:
Força os aplicativos a usar o idioma padrão para saída:
e força a classificação a bytes:
fonte
LC_ALL
é a variável de ambiente que substitui todas as outras configurações de localização ( exceto$LANGUAGE
em algumas circunstâncias ).Diferentes aspectos das localizações (como o separador de mil caracteres ou o ponto decimal, o conjunto de caracteres, a ordem de classificação, o mês, os nomes dos dias, o idioma ou as mensagens do aplicativo, como mensagens de erro, símbolo da moeda) podem ser definidos usando algumas variáveis de ambiente.
Você normalmente definirá
$LANG
sua preferência com um valor que identifique sua região (comofr_CH.UTF-8
se você estiver na Suíça de língua francesa, usando UTF-8). AsLC_xxx
variáveis individuais substituem um determinado aspecto.LC_ALL
substitui todos eles. Olocale
comando, quando chamado sem argumento, fornece um resumo das configurações atuais.Por exemplo, em um sistema GNU, recebo:
Posso substituir uma configuração individual por, por exemplo:
Ou:
Ou substitua tudo por LC_ALL.
Em um script, se você deseja forçar uma configuração específica, como não sabe quais configurações o usuário forçou (possivelmente LC_ALL também), sua melhor opção, mais segura e geralmente única é forçar LC_ALL.
O
C
código de idioma é um código de idioma especial que deve ser o código de idioma mais simples. Você também pode dizer que, enquanto os outros locais são para humanos, o local C é para computadores. No código C, os caracteres são bytes únicos, o conjunto de caracteres é ASCII (bem, não é necessário, mas na prática estará nos sistemas que a maioria de nós utilizará), a ordem de classificação é baseada nos valores de bytes, o idioma geralmente é inglês dos EUA (embora para mensagens do aplicativo (em oposição a itens como nomes de mês ou dia ou mensagens das bibliotecas do sistema), fique a critério do autor do aplicativo) e itens como símbolos de moeda não estejam definidos.Em alguns sistemas, há uma diferença com o código do idioma POSIX em que, por exemplo, a ordem de classificação para caracteres não ASCII não está definida.
Você geralmente executa um comando com LC_ALL = C para evitar que as configurações do usuário interfiram no seu script. Por exemplo, se você deseja
[a-z]
combinar os 26 caracteres ASCII dea
paraz
, você deve definirLC_ALL=C
.Nos sistemas GNU,
LC_ALL=C
eLC_ALL=POSIX
(ouLC_MESSAGES=C|POSIX
) substituem$LANGUAGE
, enquantoLC_ALL=anything-else
não.Alguns casos em que você normalmente precisa definir
LC_ALL=C
:sort -u
ousort ... | uniq...
. Em muitos locais diferentes de C, em alguns sistemas (principalmente os GNU), alguns caracteres têm a mesma ordem de classificação .sort -u
não relata linhas exclusivas, mas uma de cada grupo de linhas que têm a mesma ordem de classificação. Portanto, se você quiser linhas exclusivas, precisará de um código de idioma em que os caracteres sejam byte e todos os caracteres terão uma ordem de classificação diferente (que oC
código de idioma garante).=
operador compatível com POSIXexpr
ou ao==
operador compatível com POSIXawk
(mawk
egawk
não é POSIX a esse respeito), que não verifica se duas cadeias são idênticas, mas se elas são iguais.grep
. Se você deseja corresponder uma letra no idioma do usuário, usegrep '[[:alpha:]]'
e não modifiqueLC_ALL
. Mas se você quiser combinar osa-zA-Z
caracteres ASCII, precisará de umLC_ALL=C grep '[[:alpha:]]'
ou deLC_ALL=C grep '[a-zA-Z]'
¹.[a-z]
corresponde aos caracteres que ordenama
antes e depoisz
(embora com muitas APIs seja mais complicado que isso). Em outros locais, você geralmente não sabe o que são. Por exemplo, alguns códigos de idioma ignoram os casos de classificação, portanto,[a-z]
em algumas APIs, comobash
padrões, podem incluir[B-Z]
or[A-Y]
. Em muitos locais UTF-8 (incluindoen_US.UTF-8
na maioria dos sistemas),[a-z]
incluirá as letras latinas dea
paray
com diacríticos, mas não as dez
(desdez
tipos antes deles) que eu não consigo imaginar seria o que você quer (por que você gostaria de incluiré
e nãoź
?).ponto aritmético de ponto flutuante
ksh93
.ksh93
homenageia odecimal_point
cenárioLC_NUMERIC
. Se você escrever um script que contenhaa=$((1.2/7))
, ele deixará de funcionar quando executado por um usuário cuja localidade possui vírgula como separador decimal:Então você precisa de coisas como:
Como observação lateral: o
,
separador decimal entra em conflito com o,
operador aritmético, o que pode causar ainda mais confusão.grep '<.*>'
procurar linhas contendo a<
,>
pair não funcionará se você estiver em um código de idioma UTF-8 e a entrada estiver codificada em um conjunto de caracteres de 8 bits de byte único como iso8859-15. Isso.
ocorre porque apenas os caracteres correspondentes e caracteres não ASCII em iso8859-15 provavelmente não formarão um caractere válido no UTF-8. Por outro lado,LC_ALL=C grep '<.*>'
funcionará porque qualquer valor de byte forma um caractere válido noC
código do idioma.A qualquer momento em que você processa dados de entrada ou dados de saída que não são destinados a / para humanos. Se estiver conversando com um usuário, convém usar a convenção e o idioma, mas, por exemplo, se você gerar alguns números para alimentar outro aplicativo que espera pontos decimais no estilo inglês ou nomes de meses em inglês, convém defina LC_ALL = C:
Isso também se aplica a coisas como comparação sem distinção entre maiúsculas e minúsculas (como em
grep -i
) e conversão de maiúsculas (awk
'stoupper()
,dd conv=ucase
...). Por exemplo:não é garantido que ele corresponda na
I
localidade do usuário. Em algumas localidades turcas por exemplo, não faz como maiúsculasi
éİ
(note o ponto) lá e minúsculasI
éı
(observe o ponto em falta).¹ Dependendo da codificação do texto, isso não é necessariamente a coisa certa a se fazer. Isso é válido para conjuntos de caracteres UTF-8 ou de byte único (como iso-8859-1), mas não necessariamente conjuntos de caracteres multibyte que não sejam UTF-8.
Por exemplo, se você estiver em uma
zh_HK.big5hkscs
localidade (Hong Kong, usando a variante Hong Kong da codificação de caracteres chineses BIG5) e desejar procurar letras em inglês em um arquivo codificado nesses conjuntos de caracteres, faça o seguinte:ou
estaria errado, porque nesse conjunto de caracteres (e muitos outros, mas pouco usado desde que o UTF-8 foi lançado), muitos caracteres contêm bytes que correspondem à codificação ASCII dos caracteres A-Za-z. Por exemplo, todos
A䨝䰲丕乙乜你再劀劈呸哻唥唧噀噦嚳坽
(e muitos mais) contêm a codificação deA
.䨝
é 0x96 0x41 eA
é 0x41 como em ASCII. Portanto, o nossoLC_ALL=C grep '[a-zA-Z]'
corresponderia às linhas que contêm esses caracteres, pois interpretaria mal essas seqüências de bytes.funcionaria, mas somente se
LC_ALL
não estiver definido de outra forma (o que substituiriaLC_COLLATE
). Então você pode ter que fazer:se você quiser procurar letras em inglês em um arquivo codificado na codificação da localidade.
fonte
C
localidade é necessária apenas para suportar o "conjunto de caracteres portátil" (ASCII 0-127), e o comportamento para caracteres> 127 é tecnicamente não especificado . Na prática, a maioria dos programas os trata como dados opacos e os repassa como você descreveu. Mas não todos: em particular, Ruby pode engasgar com dados de caracteres com bytes> 127 se estiver executando noC
local. Sinceramente, não sei se isso é tecnicamente "compatível", mas já vimos isso na natureza .perl
's\x{7FFFFFFFFFFFFFFF}
) e enquanto o intervalo de pontos de código Unicode foi arbitrariamente restrito a U + 10FFFF (devido à limitação de design UTF-16), algumas ferramentas ainda reconhecem / produzem caracteres de 6 bytes. Isso é o que eu quis dizer com caracteres de 6 bytes. Na semântica do Unix, um caractere é um ponto de código. Seus mais de um "código" de ponto de código são geralmente referenciados como clusters de graphem para desambiguar os caracteres.C
é o código de idioma padrão, "POSIX" é o alias de "C". Eu acho que "C" é derivado de ANSI-C. Talvez o ANSI-C defina o código do idioma "POSIX".fonte
C
nome da localidade derive de "ANSI C".Até onde eu sei, o OS X usa a ordem de intercalação de pontos de código nos códigos de idioma UTF-8, portanto é uma exceção a alguns dos pontos mencionados na resposta de Stéphane Chazelas.
Isso imprime 26 no OS X e 310 no Ubuntu:
O código abaixo não imprime nada no OS X, indicando que a entrada está classificada. Os seis caracteres substitutos removidos causam um erro ilegal na sequência de bytes.
O código abaixo não imprime nada no OS X, indicando que não há dois pontos de código consecutivos (pelo menos entre U + 000B e U + D7FF) que tenham a mesma ordem de intercalação.
(Os exemplos acima são usados
%b
porqueprintf \\U25
resultam em um erro no zsh.)Alguns caracteres e sequências de caracteres que têm a mesma ordem de intercalação nos sistemas GNU não têm a mesma ordem de intercalação no OS X. Isso imprime ① primeiro no OS X (usando o OS X
sort
ou GNUsort
), mas Ubuntu primeiro no Ubuntu:Isso imprime três linhas no OS X (usando o OS X
sort
ou o GNUsort
), mas uma linha no Ubuntu:fonte
Parece que
LC_COLLATE
controla a "ordem alfabética" usada por ls também. A localidade dos EUA classificará da seguinte maneira:basicamente ignorando os períodos. Você pode preferir:
Eu certamente faço. Configuração
LC_COLLATE
paraC
realizar isso. Observe que ele também classificará minúsculas depois de todas as maiúsculas:fonte