A cosa serve il Cvalore LC_ALLnei sistemi simili a Unix?
So che forza lo stesso locale per tutti gli aspetti, ma cosa fa C?
A cosa serve il Cvalore LC_ALLnei sistemi simili a Unix?
So che forza lo stesso locale per tutti gli aspetti, ma cosa fa C?
Risposte:
Forza le applicazioni a utilizzare la lingua predefinita per l'output:
$ LC_ALL=es_ES man
¿Qué página de manual desea?
$ LC_ALL=C man
What manual page do you want?
e forza l'ordinamento in base al byte:
$ 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è la variabile di ambiente che sovrascrive tutte le altre impostazioni di localizzazione ( tranne $LANGUAGEin alcune circostanze ).
È possibile impostare diversi aspetti delle localizzazioni (come il carattere separatore delle migliaia o il punto decimale, il set di caratteri, l'ordinamento, i nomi di mese, giorno, lingua o applicazione come messaggi di errore, simbolo di valuta) utilizzando alcune variabili di ambiente.
In genere imposterai le $LANGtue preferenze con un valore che identifica la tua regione (come fr_CH.UTF-8se fossi nella Svizzera francese, usando UTF-8). Le singole LC_xxxvariabili hanno la precedenza su un certo aspetto. LC_ALLli sovrascrive tutti. Il localecomando, quando viene chiamato senza argomento, fornisce un riepilogo delle impostazioni correnti.
Ad esempio, su un sistema GNU, ottengo:
$ 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 ignorare una singola impostazione con ad esempio:
$ LC_TIME=fr_FR.UTF-8 date
jeudi 22 août 2013, 10:41:30 (UTC+0100)
O:
$ LC_MONETARY=fr_FR.UTF-8 locale currency_symbol
€
O sovrascrivi tutto con LC_ALL.
$ LC_ALL=C LANG=fr_FR.UTF-8 LC_MESSAGES=fr_FR.UTF-8 cat /
cat: /: Is a directory
In uno script, se si desidera forzare un'impostazione specifica, poiché non si conoscono le impostazioni che l'utente ha imposto (possibilmente anche LC_ALL), l'opzione migliore, più sicura e in genere l'unica è forzare LC_ALL.
La Clocale è una locale speciale che dovrebbe essere la locale più semplice. Si potrebbe anche dire che mentre le altre impostazioni locali sono per gli umani, le impostazioni locali C sono per i computer. Nella locale C, i caratteri sono singoli byte, il set di caratteri è ASCII (beh, non è necessario, ma in pratica sarà nei sistemi che la maggior parte di noi potrà mai usare), l'ordinamento si basa sui valori dei byte, la lingua è solitamente l'inglese americano (anche se per i messaggi dell'applicazione (diversamente da nomi di mese o giorno o messaggi dalle librerie di sistema), è a discrezione dell'autore dell'applicazione) e cose come i simboli di valuta non sono definiti.
Su alcuni sistemi, c'è una differenza con le impostazioni locali POSIX in cui, ad esempio, l'ordinamento per i caratteri non ASCII non è definito.
Generalmente si esegue un comando con LC_ALL = C per evitare che le impostazioni dell'utente interferiscano con lo script. Ad esempio, se si desidera [a-z]abbinare i 26 caratteri ASCII da aa z, è necessario impostare LC_ALL=C.
Sui sistemi GNU LC_ALL=Ce LC_ALL=POSIX(o LC_MESSAGES=C|POSIX) sovrascrivere $LANGUAGE, mentre LC_ALL=anything-elseno.
Alcuni casi in cui in genere è necessario impostare LC_ALL=C:
sort -uoppure sort ... | uniq.... In molte lingue diverse da C, su alcuni sistemi (in particolare quelli GNU), alcuni caratteri hanno lo stesso ordinamento . sort -unon riporta righe univoche, ma uno per ogni gruppo di righe con uguale ordinamento. Quindi, se si desidera linee univoche, è necessario un locale in cui i caratteri sono byte e tutti i caratteri hanno un diverso ordinamento (che Cgarantisce il locale).=operatore conforme a POSIX expro l' ==operatore conforme a POSIX awk( mawke gawknon sono POSIX al riguardo), che non verificano se due stringhe sono identiche ma se ordinano la stessa.grep. Se intendi abbinare una lettera nella lingua dell'utente, usa grep '[[:alpha:]]'e non modificare LC_ALL. Ma se si desidera abbinare i a-zA-Zcaratteri ASCII, è necessario uno LC_ALL=C grep '[[:alpha:]]'o LC_ALL=C grep '[a-zA-Z]'¹. [a-z]corrisponde ai caratteri che ordinano dopo ae prima z(anche se con molte API è più complicato di così). In altri locali, generalmente non sai cosa siano. Ad esempio, alcune impostazioni locali ignorano il caso dell'ordinamento, quindi [a-z]in alcune API come i bashpattern, potrebbero includere [B-Z]o [A-Y]. In molti locali UTF-8 (incluso en_US.UTF-8nella maggior parte dei sistemi), [a-z]includeranno le lettere latine da aa ycon segni diacritici ma non quelli di z(poichézprima di loro) che non riesco a immaginare sarebbe quello che vuoi (perché dovresti includere ée non ź?).aritmetica in virgola mobile in ksh93. ksh93onora l' decimal_pointambientazione LC_NUMERIC. Se scrivi uno script che contiene a=$((1.2/7)), smetterà di funzionare quando eseguito da un utente la cui locale ha la virgola come separatore decimale:
$ 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
Quindi hai bisogno di cose come:
#! /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
Come nota a margine: il ,separatore decimale è in conflitto con l' ,operatore aritmetico che può causare ancora più confusione.
grep '<.*>'per cercare le righe che contengono un <, >pair non funzionerà se ci si trova in una locale UTF-8 e l'input è codificato in un set di caratteri a 8 bit a byte singolo come iso8859-15. Questo perché .è probabile che solo caratteri corrispondenti e caratteri non ASCII in iso8859-15 non formino un carattere valido in UTF-8. D'altra parte, LC_ALL=C grep '<.*>'funzionerà perché qualsiasi valore di byte forma un carattere valido nella Clocale.In qualsiasi momento in cui si elaborano dati di input o dati di output che non sono previsti da / per un essere umano. Se stai parlando con un utente, potresti voler usare la loro convenzione e la loro lingua, ma per esempio, se generi alcuni numeri per alimentare un'altra applicazione che prevede punti decimali in stile inglese o nomi di mesi in inglese, ti consigliamo di impostare 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
Ciò vale anche per le cose come confronto case insensitive (come in grep -i) e la conversione caso ( awk's toupper(), dd conv=ucase...). Per esempio:
grep -i i
non è garantito che corrisponda Ialle impostazioni internazionali dell'utente. In alcuni locali turchi, per esempio, non è così come maiuscolo iè İ(notare il punto) non vi e minuscole Iè ı(notare il punto mancante).
¹ A seconda della codifica del testo, questa non è necessariamente la cosa giusta da fare. Questo è valido per i set di caratteri UTF-8 o a byte singolo (come iso-8859-1), ma non necessariamente per i set di caratteri multibyte non UTF-8.
Ad esempio, se ti trovi in una zh_HK.big5hkscslocale (Hong Kong, usando la variante di Hong Kong della codifica dei caratteri cinesi BIG5) e vuoi cercare lettere inglesi in un file codificato in quei set di caratteri, facendo una delle seguenti operazioni:
LC_ALL=C grep '[[:alpha:]]'
o
LC_ALL=C grep '[a-zA-Z]'
sarebbe sbagliato, perché in quel set di caratteri (e molti altri, ma poco usato da quando è uscito UTF-8), molti caratteri contengono byte che corrispondono alla codifica ASCII dei caratteri A-Za-z. Ad esempio, tutti A䨝䰲丕乙乜你再劀劈呸哻唥唧噀噦嚳坽(e molti altri) contengono la codifica di A. 䨝è 0x96 0x41 ed Aè 0x41 come in ASCII. Quindi il nostro LC_ALL=C grep '[a-zA-Z]'corrisponderebbe su quelle righe che contengono quei caratteri poiché interpreterebbe erroneamente quelle sequenze di byte.
LC_COLLATE=C grep '[A-Za-z]'
funzionerebbe, ma solo se LC_ALLnon diversamente impostato (che avrebbe la precedenza LC_COLLATE). Quindi potresti finire per dover fare:
grep '[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]'
se si desidera cercare lettere inglesi in un file codificato nella codifica della locale.
Clocale è richiesta solo per supportare il "set di caratteri portatile" (ASCII 0-127) e il comportamento per i caratteri> 127 non è tecnicamente specificato . In pratica, la maggior parte dei programmi li tratterà come dati opachi e li passerà come descritto. Ma non tutti: in particolare, Ruby può soffocare sui dati char con byte> 127 se in esecuzione nella Clocale. Onestamente non so se questo sia tecnicamente "conforme", ma l'abbiamo visto in libertà .
perl's \x{7FFFFFFFFFFFFFFF}) e mentre la gamma di punti di codice Unicode è stato arbitrariamente limitato a U + 10FFFF (a causa della limitazione del design UTF-16), alcuni strumenti riconoscono / producono ancora caratteri a 6 byte. Questo è ciò che intendevo per caratteri a 6 byte. Nella semantica Unix, un carattere è un punto di codice. I tuoi più di un "personaggio" di punti di codice sono più comunemente indicati come gruppi graphem per chiarire i caratteri.
Cè la locale predefinita, "POSIX" è l'alias di "C". Immagino che "C" sia derivato da ANSI-C. Forse ANSI-C definisce la locale "POSIX".
Cnome della locale derivi da "ANSI C".
Per quanto ne so, OS X utilizza l'ordine di confronto dei punti di codice in locali UTF-8, quindi è un'eccezione ad alcuni dei punti menzionati nella risposta di Stéphane Chazelas.
Questo stampa 26 in OS X e 310 in Ubuntu:
export LC_ALL=en_US.UTF-8
printf %b $(printf '\\U%08x\\n' $(seq $((0x11)) $((0x10ffff))))|grep -a '[a-z]'|wc -l
Il codice seguente non stampa nulla in OS X, indicando che l'input è ordinato. I sei caratteri surrogati che vengono rimossi causano un errore di sequenza di byte non valido.
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
Il codice seguente non stampa nulla in OS X, indicando che non ci sono due punti di codice consecutivi (almeno tra U + 000B e U + D7FF) che hanno lo stesso ordine di confronto.
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
(Gli esempi sopra riportati usano %bperché printf \\U25provoca un errore in zsh.)
Alcuni caratteri e sequenze di caratteri che hanno lo stesso ordine di confronto nei sistemi GNU non hanno lo stesso ordine di confronto in OS X. Questo stampa ① prima in OS X (usando OS X sorto GNU sort) ma ② prima in Ubuntu:
export LC_ALL=en_US.UTF-8;printf %s\\n ② ①|sort
Questo stampa tre linee in OS X (usando OS X sorto GNU sort) ma una linea in Ubuntu:
export LC_ALL=en_US.UTF-8;printf %b\\n \\u0d4c \\u0d57 \\u0d46\\u0d57|sort -u
Sembra che LC_COLLATEcontrolli anche l '"ordine alfabetico" usato da ls. Le impostazioni internazionali statunitensi verranno ordinate come segue:
a.C
aFilename.C
aFilename.H
a.H
praticamente ignorando i periodi. Potresti preferire:
a.C
a.H
aFilename.C
aFilename.H
Certamente. Impostazione LC_COLLATEper Crealizzare questo. Si noti che ordinerà anche in minuscolo dopo tutte le maiuscole:
A.C
A.H
AFilename.C
a.C
a.H
xclockwarning (Missing charsets in String to FontSet conversion), sarà meglio se lo useraiLC_ALL=C.UTF-8per evitare problemi con il cirillico. Per impostare questa variabile d'ambiente è necessario aggiungere la seguente riga alla fine del~/.bashrcfile -export LC_ALL=C.UTF-8