Di semua shell yang saya ketahui, rm [A-Z]*
menghapus semua file yang dimulai dengan huruf besar, tetapi dengan bash ini menghapus semua file yang dimulai dengan huruf.
Karena masalah ini ada di Linux dan Solaris dengan bash-3 dan bash-4, itu tidak mungkin merupakan bug yang disebabkan oleh pencocokan pola kereta di libc atau definisi lokal yang salah dikonfigurasi.
Apakah perilaku aneh dan berisiko ini disengaja atau hanya bug yang tidak diperbaiki sejak bertahun-tahun?
Jawaban yang Diterima:
Perhatikan bahwa saat menggunakan ekspresi rentang seperti [a-z], huruf dari kasus lain mungkin disertakan, tergantung pada setelan LC_COLLATE.
LC_COLLATE
adalah variabel yang menentukan urutan susunan yang digunakan saat menyortir hasil perluasan nama jalur, dan menentukan perilaku ekspresi rentang, kelas ekuivalensi, dan urutan susunan dalam perluasan nama jalur dan pencocokan pola.
Pertimbangkan hal berikut:
$ 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
Perhatikan ketika perintah echo [a-z]
dipanggil, output yang diharapkan adalah semua file dengan karakter huruf kecil. Juga, dengan echo [A-Z]
, file dengan karakter huruf besar diharapkan.
Susunan standar dengan lokal seperti en_US
memiliki urutan sebagai berikut:
aAbBcC...xXyYzZ
- Antara
a
danz
(dalam[a-z]
) adalah SEMUA huruf besar, kecualiZ
. - Antara
A
danZ
(dalam[A-Z]
) adalah SEMUA huruf kecil, kecualia
.
Lihat:
aAbBcC[...]xXyYzZ
| |
from a to z
aAbBcC[...]xXyYzZ
| |
from A to Z
Jika Anda mengubah LC_COLLATE
variabel ke C
terlihat seperti yang diharapkan:
$ export LC_COLLATE=C
$ echo [a-z]
a b c x y z
$ echo [A-Z]
A B C X Y Z
Jadi, ini bukan bug , ini adalah masalah pengumpulan .
Alih-alih ekspresi rentang, Anda dapat menggunakan kelas karakter yang ditentukan POSIX, seperti upper
atau lower
. Mereka juga bekerja dengan LC_COLLATE
yang berbeda konfigurasi dan bahkan dengan karakter beraksen :
$ echo [[:lower:]]
a b c x y z à è é
$ echo [[:upper:]]
A B C X Y Z