Ve všech shellech, které znám, rm [A-Z]*
odstraní všechny soubory, které začínají velkým písmenem, ale s bash to odstraní všechny soubory, které začínají písmenem.
Protože tento problém existuje na Linuxu a Solarisu s bash-3 a bash-4, nemůže to být chyba způsobená chybným porovnáváním vzorů v knihovně libc nebo chybně nakonfigurovanou definicí národního prostředí.
Je toto podivné a riskantní chování zamýšleno nebo je to jen chyba, která existuje již mnoho let neopravená?
Přijatá odpověď:
Pamatujte, že při použití výrazů rozsahu jako [a-z] mohou být v závislosti na nastavení LC_COLLATE zahrnuta i jiná písmena.
LC_COLLATE
je proměnná, která určuje pořadí řazení použité při třídění výsledků rozšíření názvu cesty a určuje chování výrazů rozsahu, tříd ekvivalence a porovnávacích sekvencí v rámci rozšíření názvu cesty a porovnávání vzorů.
Zvažte následující:
$ touch a A b B c C x X y Y z Z
$ ls
a A b B c C x X y Y z Z
$ echo [a-z] # Note the missing uppercase "Z"
a A b B c C x X y Y z
$ echo [A-Z] # Note the missing lowercase "a"
A b B c C x X y Y z Z
Všimněte si, že příkaz echo [a-z]
zavoláno, očekávaným výstupem budou všechny soubory s malými písmeny. Také s echo [A-Z]
, lze očekávat soubory s velkými písmeny.
Standardní řazení s národními prostředími, jako je en_US
mají následující pořadí:
aAbBcC...xXyYzZ
- Mezi
a
az
(v[a-z]
) jsou VŠECHNA velká písmena, kroměZ
. - Mezi
A
aZ
(v[A-Z]
) jsou VŠECHNA malá písmena, kroměa
.
Viz:
aAbBcC[...]xXyYzZ
| |
from a to z
aAbBcC[...]xXyYzZ
| |
from A to Z
Pokud změníte LC_COLLATE
proměnná na C
vypadá to podle očekávání:
$ export LC_COLLATE=C
$ echo [a-z]
a b c x y z
$ echo [A-Z]
A B C X Y Z
Takže to není chyba , je to problém s řazením .
Místo výrazů rozsahu můžete použít třídy znaků definované v POSIX, jako je upper
nebo lower
. Pracují také s různými LC_COLLATE
konfigurace a dokonce i s znaky s diakritikou :
$ echo [[:lower:]]
a b c x y z à è é
$ echo [[:upper:]]
A B C X Y Z