Ordine di confronto tramite LC_COLLATE
definisce non solo l'ordinamento dei singoli caratteri, ma anche il significato degli intervalli di caratteri. O lo fa? Considera il seguente snippet:
unset LANGUAGE LC_ALL
echo B | LC_COLLATE=en_US grep '[a-z]'
Intuitivamente, B
non è in [a-z]
, quindi questo non dovrebbe produrre nulla. Questo è ciò che accade su Ubuntu 8.04 o 10.04. Ma su alcune macchine che eseguono Debian lenny o squeeze, B
viene trovato, perché l'intervallo a-z
include tutto ciò che è compreso tra a
e z
nell'ordine di confronto, comprese le lettere maiuscole B
tramite Z
.
Tutti i sistemi testati hanno il en_US
locale generato. Ho anche provato a variare la locale:sulle macchine in cui B
è abbinato sopra, lo stesso accade in ogni locale disponibile (principalmente in latino:{en_{AU,CA,GB,IE,US},fr_FR,it_IT,es_ES,de_DE}{iso8859-1,iso8859-15,utf-8}
, anche le versioni locali cinesi) eccetto il giapponese (in qualsiasi codifica disponibile) e C
/POSIX
.
Cosa significano gli intervalli di caratteri nelle espressioni regolari , quando vai oltre l'ASCII? Perché c'è una differenza tra alcune installazioni Debian da un lato e altre installazioni Debian e Ubuntu dall'altro? Come si comportano gli altri sistemi? Chi ha ragione e contro chi dovrebbe essere segnalato un bug?
(Nota che sto chiedendo specificamente il comportamento di intervalli di caratteri come [a-z]
in en_US
locali, principalmente su sistemi basati su GNU libc. Non sto chiedendo come abbinare le lettere minuscole o le lettere minuscole ASCII.)
Su due macchine Debian, una dove B
è in [a-z]
e uno in cui non lo è, l'output di LC_COLLATE=en_US locale -k LC_COLLATE
è
collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=1
collate-codeset="ISO-8859-1"
e l'output di LC_COLLATE=en_US.utf8 locale -k LC_COLLATE
è
collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=2039
collate-codeset="UTF-8"
Risposta accettata:
Se stai usando qualcosa di diverso da C
locale, non dovresti usare intervalli come [a-z]
poiché questi dipendono dalla località e non sempre danno i risultati che ti aspetteresti. Oltre al problema del caso che hai già riscontrato, alcune impostazioni locali trattano i caratteri con segni diacritici (ad es. á ) lo stesso del carattere di base (cioè a ).
Invece, usa una classe di caratteri denominata:
echo B | grep '[[:lower:]]'
Questo darà sempre il risultato corretto per la locale. Tuttavia, devi scegliere la lingua in modo che rifletta il significato sia del testo di input che del test che stai cercando di applicare.
Correlati:Php:imagechar — Disegna un carattere orizzontalmente
Ad esempio, se hai bisogno di trovare un valore di byte particolare, usa il C
locale, sempre disponibile:
echo B | LANG=C grep '[a-z]'
Se questo non funziona come previsto, è davvero un bug.