Qual é o Cvalor para LC_ALLsistemas Unix?
Eu sei que ele força o mesmo local para todos os aspectos, mas o que Cfaz?
Qual é o Cvalor para LC_ALLsistemas Unix?
Eu sei que ele força o mesmo local para todos os aspectos, mas o que Cfaz?
Respostas:
Força os aplicativos a usar o idioma padrão para saída:
$ LC_ALL=es_ES man
¿Qué página de manual desea?
$ LC_ALL=C man
What manual page do you want?
e força a classificação a bytes:
$ LC_ALL=en_US sort <<< $'a\nb\nA\nB'
a
A
b
B
$ LC_ALL=C sort <<< $'a\nb\nA\nB'
A
B
a
b
LC_ALLé a variável de ambiente que substitui todas as outras configurações de localização ( exceto $LANGUAGEem 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á $LANGsua preferência com um valor que identifique sua região (como fr_CH.UTF-8se você estiver na Suíça de língua francesa, usando UTF-8). As LC_xxxvariáveis individuais substituem um determinado aspecto. LC_ALLsubstitui todos eles. O localecomando, quando chamado sem argumento, fornece um resumo das configurações atuais.
Por exemplo, em um sistema GNU, recebo:
$ locale
LANG=en_GB.UTF-8
LANGUAGE=
LC_CTYPE="en_GB.UTF-8"
LC_NUMERIC="en_GB.UTF-8"
LC_TIME="en_GB.UTF-8"
LC_COLLATE="en_GB.UTF-8"
LC_MONETARY="en_GB.UTF-8"
LC_MESSAGES="en_GB.UTF-8"
LC_PAPER="en_GB.UTF-8"
LC_NAME="en_GB.UTF-8"
LC_ADDRESS="en_GB.UTF-8"
LC_TELEPHONE="en_GB.UTF-8"
LC_MEASUREMENT="en_GB.UTF-8"
LC_IDENTIFICATION="en_GB.UTF-8"
LC_ALL=
Posso substituir uma configuração individual por, por exemplo:
$ LC_TIME=fr_FR.UTF-8 date
jeudi 22 août 2013, 10:41:30 (UTC+0100)
Ou:
$ LC_MONETARY=fr_FR.UTF-8 locale currency_symbol
€
Ou substitua tudo por LC_ALL.
$ LC_ALL=C LANG=fr_FR.UTF-8 LC_MESSAGES=fr_FR.UTF-8 cat /
cat: /: Is a directory
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 Ccó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 de apara z, você deve definir LC_ALL=C.
Nos sistemas GNU, LC_ALL=Ce LC_ALL=POSIX(ou LC_MESSAGES=C|POSIX) substituem $LANGUAGE, enquanto LC_ALL=anything-elsenão.
Alguns casos em que você normalmente precisa definir LC_ALL=C:
sort -uou sort ... | uniq.... Em muitos locais diferentes de C, em alguns sistemas (principalmente os GNU), alguns caracteres têm a mesma ordem de classificação . sort -unã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 o Ccódigo de idioma garante).=operador compatível com POSIX exprou ao ==operador compatível com POSIX awk( mawke gawknã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, use grep '[[:alpha:]]'e não modifique LC_ALL. Mas se você quiser combinar os a-zA-Zcaracteres ASCII, precisará de um LC_ALL=C grep '[[:alpha:]]'ou de LC_ALL=C grep '[a-zA-Z]'¹. [a-z]corresponde aos caracteres que ordenam aantes e depois z(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, como bashpadrões, podem incluir [B-Z]or [A-Y]. Em muitos locais UTF-8 (incluindo en_US.UTF-8na maioria dos sistemas), [a-z]incluirá as letras latinas de apara ycom diacríticos, mas não as de z(desdeztipos 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. ksh93homenageia o decimal_pointcenário LC_NUMERIC. Se você escrever um script que contenha a=$((1.2/7)), ele deixará de funcionar quando executado por um usuário cuja localidade possui vírgula como separador decimal:
$ ksh93 -c 'echo $((1.1/2))'
0.55
$ LANG=fr_FR.UTF-8 ksh93 -c 'echo $((1.1/2))'
ksh93: 1.1/2: arithmetic syntax error
Então você precisa de coisas como:
#! /bin/ksh93 -
float input="$1" # get it as input from the user in his locale
float output
arith() { typeset LC_ALL=C; (($@)); }
arith output=input/1.2 # use the dot here as it will be interpreted
# under LC_ALL=C
echo "$output" # output in the user's locale
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 no Ccó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:
$ printf '%g\n' 1e-2
0,01
$ LC_ALL=C printf '%g\n' 1e-2
0.01
$ date +%b
août
$ LC_ALL=C date +%b
Aug
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's toupper(), dd conv=ucase...). Por exemplo:
grep -i i
não é garantido que ele corresponda na Ilocalidade do usuário. Em algumas localidades turcas por exemplo, não faz como maiúsculas ié İ(note o ponto) lá e minúsculas Ié ı(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.big5hkscslocalidade (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:
LC_ALL=C grep '[[:alpha:]]'
ou
LC_ALL=C grep '[a-zA-Z]'
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 de A. 䨝é 0x96 0x41 e Aé 0x41 como em ASCII. Portanto, o nosso LC_ALL=C grep '[a-zA-Z]'corresponderia às linhas que contêm esses caracteres, pois interpretaria mal essas seqüências de bytes.
LC_COLLATE=C grep '[A-Za-z]'
funcionaria, mas somente se LC_ALLnão estiver definido de outra forma (o que substituiria LC_COLLATE). Então você pode ter que fazer:
grep '[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]'
se você quiser procurar letras em inglês em um arquivo codificado na codificação da localidade.
Clocalidade é 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 no Clocal. 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".
Cnome 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:
export LC_ALL=en_US.UTF-8
printf %b $(printf '\\U%08x\\n' $(seq $((0x11)) $((0x10ffff))))|grep -a '[a-z]'|wc -l
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.
export LC_ALL=en_US.UTF-8
for ((i=1;i<=0x1fffff;i++));do
x=$(printf %04x $i)
[[ $x = @(000a|d800|db7f|db80|dbff|dc00|dfff) ]]&&continue
printf %b \\U$x\\n
done|sort -c
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.
export LC_ALL=en_US.UTF-8
for ((i=0xb;i<=0xd7fe;i++));do
printf %b $(printf '\\U%08x\\n' $((i+1)) $i)|sort -c 2>/dev/null&&echo $i
done
(Os exemplos acima são usados %bporque printf \\U25resultam 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 sortou GNU sort), mas Ubuntu primeiro no Ubuntu:
export LC_ALL=en_US.UTF-8;printf %s\\n ② ①|sort
Isso imprime três linhas no OS X (usando o OS X sortou o GNU sort), mas uma linha no Ubuntu:
export LC_ALL=en_US.UTF-8;printf %b\\n \\u0d4c \\u0d57 \\u0d46\\u0d57|sort -u
Parece que LC_COLLATEcontrola a "ordem alfabética" usada por ls também. A localidade dos EUA classificará da seguinte maneira:
a.C
aFilename.C
aFilename.H
a.H
basicamente ignorando os períodos. Você pode preferir:
a.C
a.H
aFilename.C
aFilename.H
Eu certamente faço. Configuração LC_COLLATEpara Crealizar isso. Observe que ele também classificará minúsculas depois de todas as maiúsculas:
A.C
A.H
AFilename.C
a.C
a.H
xclockaviso (Missing charsets in String to FontSet conversion), será melhor usar issoLC_ALL=C.UTF-8para evitar problemas com o cirílico. Para definir essa variável de ambiente, você deve adicionar a seguinte linha ao final do~/.bashrcarquivo -export LC_ALL=C.UTF-8