Sensitivitas huruf pada skrip shell

10

Pertimbangkan skrip Bash ini:

#!/bin/bash
echo Enter any character
read char
case $char in
    [a-z]) echo Lower case letter
            ;;
    [A-Z]) echo Upper case letter
            ;;
    [0-9]) echo Number
            ;;
    ?) echo Special char
            ;;
    *) echo You entered more than one character 
            ;;
esac

Jika saya memasukkan 'a', hasilnya adalah huruf kecil , dan itu sama untuk 'A' ... Bagaimana saya mengatasinya?

Ramana Reddy
sumber
Ketika Anda memposting skrip pastikan Anda menggunakan format kode, untuk menjaga spasi. Juga, apa pertanyaan sebenarnya? Saya tidak yakin apa yang Anda maksud ...
AJefferiss
2
@Arronical tidak perlu, gema dapat menangani kata-kata yang dipesan echo if case then do.
terdon
Untuk masalah serupa, tetapi berurusan dengan pengurutan, lihat askubuntu.com/questions/597924/...
Joe

Jawaban:

20
#!/bin/bash
echo 'enter any character'
read char
case $char in
[[:lower:]]) echo 'lower case letter'
    ;;
[[:upper:]]) echo 'upper case letter'
    ;;
[0-9]) echo 'number'
    ;;
?) echo 'special char'
    ;;
*) echo 'u entered more than one char' 
    ;;
esac  

Untuk informasi lebih lanjut tentang ekspresi reguler huruf kecil dari [az] dan ekspresi reguler huruf besar dari [AZ] di bash lihat Mengapa pernyataan case case-sensitive ketika nocasematch dimatikan? .

karel
sumber
6
Sebagai lanjutan dari ini, alih-alih [0-9]Anda dapat menggunakan [[:digit:]]. Anda dapat menemukan lebih banyak contoh di man grep, atau kelas karakter Google posix .
Paddy Landau
21

Masalahnya adalah bahwa rentang karakter [a-z]sebenarnya termasuk huruf besar. Ini dijelaskan dalam manual bash :

Dalam ekspresi braket, ekspresi rentang terdiri dari dua karakter yang dipisahkan oleh tanda hubung. Ini cocok dengan setiap karakter yang menyortir antara dua karakter, inklusif. Di lokal C default, urutan pengurutan adalah urutan karakter asli; misalnya, '[iklan]' sama dengan '[abcd]'. Di lokal lain, urutan pengurutan tidak ditentukan, dan '[iklan]' mungkin sama dengan '[abcd]' atau untuk '[aBbCcDd]' , atau mungkin gagal untuk mencocokkan karakter apa pun, atau set karakter yang pertandingan bahkan mungkin tidak menentu. Untuk mendapatkan interpretasi tradisional ekspresi braket, Anda dapat menggunakan lokal 'C' dengan mengatur variabel lingkungan LC_ALL ke nilai 'C'.

Menggambarkan:

$ case B in [a-c]) echo YES;;  *) echo NO;; esac
YES
$ LC_ALL=C; case B in [a-c]) echo YES;; *) echo NO;; esac
NO

Jadi, yang terjadi adalah bahwa di tempat Anda (yang tidak C), [a-c]sebenarnya [aAbBcC]. Itu sebabnya Anda harus menggunakan kelas karakter POSIX seperti yang disarankan oleh @karel.

terdon
sumber
4
Lebih tepatnya, Anda perlu mengatur LC_COLLATEke C, tidak apa-apa untuk pengaturan lokal lainnya menjadi berbeda. Pengaturan LC_COLLATEuntuk apa pun tetapi Cjarang merupakan ide yang baik tetapi sayangnya Ubuntu melakukannya (itu bukan satu-satunya penyebab sejauh ini).
Gilles 'SANGAT berhenti menjadi jahat'