Groß- und Kleinschreibung bei Shell-Skripten

10

Betrachten Sie dieses Bash-Skript:

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

Wenn ich 'a' eingebe, ist die Ausgabe ein Kleinbuchstabe und für 'A' dasselbe ... Wie überwinde ich das?

Ramana Reddy
quelle
Wenn Sie ein Skript veröffentlichen, stellen Sie sicher, dass Sie das Codeformat verwenden, um das Leerzeichen beizubehalten. Und was ist die eigentliche Frage? Ich bin nicht sicher, was du meinst ...
AJefferiss
2
@Arronical keine Notwendigkeit, Echo kann mit reservierten Wörtern umgehen echo if case then do.
Terdon
Für ein ähnliches Problem, aber mit Sortierung, siehe askubuntu.com/questions/597924/…
Joe

Antworten:

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  

Weitere Informationen zum regulären Ausdruck von [az] in Kleinbuchstaben und zum regulären Ausdruck von [AZ] in Großbuchstaben in bash finden Sie unter Warum wird bei der Groß- / Kleinschreibung nicht zwischen Groß- und Kleinschreibung unterschieden, wenn nocasematch deaktiviert ist? .

Karel
quelle
6
Im Anschluss daran können Sie stattdessen [0-9]verwenden [[:digit:]]. Weitere Beispiele finden Sie in man grepoder in Google Posix-Zeichenklassen .
Paddy Landau
21

Das Problem ist, dass der Zeichenbereich [a-z]tatsächlich die Großbuchstaben enthält. Dies wird im Bash-Handbuch erklärt :

Innerhalb eines Klammerausdrucks besteht ein Bereichsausdruck aus zwei Zeichen, die durch einen Bindestrich getrennt sind. Es stimmt mit jedem einzelnen Zeichen überein, das zwischen den beiden Zeichen einschließlich sortiert. Im Standardgebietsschema C ist die Sortierreihenfolge die native Zeichenreihenfolge. Beispiel: '[ad]' entspricht '[abcd]'. In anderen Gebietsschemas ist die Sortierreihenfolge nicht angegeben, und '[ad]' entspricht möglicherweise '[abcd]' oder '[aBbCcDd]' , oder es stimmt möglicherweise nicht mit einem Zeichen oder dem darin enthaltenen Zeichensatz überein Übereinstimmungen können sogar unberechenbar sein. Um die traditionelle Interpretation von Klammerausdrücken zu erhalten, können Sie das Gebietsschema 'C' verwenden, indem Sie die Umgebungsvariable LC_ALL auf den Wert 'C' setzen.

Um zu veranschaulichen:

$ 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

Also, was passiert ist, dass in Ihrem Gebietsschema (was nicht ist C) [a-c]tatsächlich ist [aAbBcC]. Aus diesem Grund sollten Sie stattdessen die von @karel vorgeschlagenen POSIX-Zeichenklassen verwenden.

Terdon
quelle
4
Genauer gesagt, müssen Sie Satz LC_COLLATEan C, anders zu sein , es ist in Ordnung für andere Ländereinstellungen. Es ist selten eine gute Idee, sich LC_COLLATEauf etwas anderes einzustellen , aber CUbuntu tut es leider (es ist bei weitem nicht der einzige Schuldige).
Gilles 'SO - hör auf böse zu sein'