Pořadí řazení prostřednictvím LC_COLLATE definuje nejen řazení jednotlivých znaků, ale také význam rozsahů znaků. nebo ano? Zvažte následující úryvek:
unset LANGUAGE LC_ALL
echo B | LC_COLLATE=en_US grep '[a-z]'
Intuitivně, B není v [a-z] , takže by to nemělo nic vydávat. To se děje na Ubuntu 8.04 nebo 10.04. Ale na některých počítačích se systémem Debian lenny nebo squeeze, B je nalezen, protože rozsah a-z zahrnuje vše, co je mezi a a z v pořadí řazení, včetně velkých písmen B přes Z .
Všechny testované systémy mají en_US vygenerováno národní prostředí. Zkoušel jsem také změnit národní prostředí:na počítačích, kde je B odpovídá výše, totéž se děje ve všech dostupných jazycích (většinou založené na latině:{en_{AU,CA,GB,IE,US},fr_FR,it_IT,es_ES,de_DE}{iso8859-1,iso8859-15,utf-8} , také čínská národní prostředí) kromě japonštiny (v jakémkoli dostupném kódování) a C /POSIX .
Co znamenají rozsahy znaků v regulárních výrazech , když překročíte ASCII? Proč je rozdíl mezi některými instalacemi Debianu na jedné straně a jinými instalacemi Debianu a Ubuntu na straně druhé? Jak se chovají ostatní systémy? Kdo má pravdu a komu by měla být chyba nahlášena?
(Všimněte si, že se konkrétně ptám na chování rozsahů znaků, jako je [a-z] v en_US locales, primárně na systémech založených na GNU libc. Neptám se, jak přiřadit malá písmena nebo malá písmena ASCII.)
Na dvou počítačích Debian, na jednom B je v [a-z] a jeden, kde není, výstup LC_COLLATE=en_US locale -k LC_COLLATE je
collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=1
collate-codeset="ISO-8859-1"
a výstup LC_COLLATE=en_US.utf8 locale -k LC_COLLATE je
collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=2039
collate-codeset="UTF-8"
Přijatá odpověď:
Pokud používáte něco jiného než C locale, neměli byste používat rozsahy jako [a-z] protože tyto jsou závislé na národním prostředí a ne vždy poskytují výsledky, které byste očekávali. Kromě problému s malými a velkými písmeny, se kterým jste se již setkali, některá národní prostředí zacházejí se znaky s diakritikou (např. a ) stejný jako základní znak (tj. a ).
Místo toho použijte pojmenovanou třídu znaků:
echo B | grep '[[:lower:]]'
To vždy poskytne správný výsledek pro národní prostředí. Musíte však vybrat národní prostředí tak, aby odráželo význam vstupního textu i testu, který se pokoušíte použít.
Související:Php:imagechar — Nakreslete znak vodorovně
Pokud například potřebujete najít konkrétní hodnotu bajtu, použijte C locale, které je vždy dostupné:
echo B | LANG=C grep '[a-z]'
Pokud to nefunguje podle očekávání, je to opravdu chyba.