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.