Rozróżnianie wielkości liter w skryptach powłoki

10

Rozważ ten skrypt Bash:

#!/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

Jeśli wprowadzę „a”, wynik będzie pisany małą literą , i to samo dla „A” ... Jak to rozwiązać?

Ramana Reddy
źródło
Podczas publikowania skryptu upewnij się, że używasz formatu kodu, aby zachować białe znaki. A jakie jest aktualne pytanie? Nie jestem pewien, co masz na myśli ...
AJefferiss,
2
@Arroniczny nie ma potrzeby, echo radzi sobie z zastrzeżonymi słowami echo if case then do.
terdon
W przypadku podobnego problemu, ale zajmującego się sortowaniem, patrz askubuntu.com/questions/597924/...
Joe

Odpowiedzi:

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  

Aby uzyskać więcej informacji na temat wyrażeń regularnych małych liter [az] i wyrażeń regularnych dużych liter [AZ] w bash, zobacz Dlaczego rozróżnianie wielkości liter w rozróżnianiu małych i małych liter jest wyłączone? .

Karel
źródło
6
Kontynuując, zamiast tego [0-9]możesz użyć [[:digit:]]. Możesz znaleźć więcej przykładów man greplub klas znaków posix Google .
Paddy Landau
21

Problem polega na tym, że zakres znaków [a-z]zawiera duże litery. Jest to wyjaśnione w podręczniku bash :

W wyrażeniu nawiasowym wyrażenie zakresu składa się z dwóch znaków oddzielonych łącznikiem. Pasuje do każdego pojedynczego znaku, który sortuje między dwoma znakami, włącznie. W domyślnych ustawieniach narodowych C sekwencją sortowania jest natywna kolejność znaków; na przykład „[reklama]” jest równoważne z „[abcd]”. W innych lokalizacjach sekwencja sortowania nie jest określona, ​​a „[ad]” może być równoważne z „[abcd]” lub „[aBbCcDd]” , lub może nie pasować do żadnego znaku lub zestawu znaków mecze mogą być nawet nieregularne. Aby uzyskać tradycyjną interpretację wyrażeń w nawiasach, można użyć ustawień regionalnych „C”, ustawiając zmienną środowiskową LC_ALL na wartość „C”.

Ilustrować:

$ 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

Tak więc dzieje się tak, że w twojej lokalizacji (która nie jest C), [a-c]tak naprawdę jest [aAbBcC]. Dlatego powinieneś używać klas znaków POSIX, jak sugeruje @karel.

terdon
źródło
4
Mówiąc dokładniej, musisz ustawić LC_COLLATEna C, że inne ustawienia regionalne mogą być inne. Ustawienie LC_COLLATEna cokolwiek, ale Crzadko jest dobrym pomysłem, ale niestety Ubuntu to robi (to zdecydowanie nie jedyny winowajca).
Gilles „SO- przestań być zły”