Mayúsculas y minúsculas en scripting de shell

10

Considere este script 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

Si ingreso 'a', la salida es minúscula y es igual para 'A' ... ¿Cómo puedo superar esto?

Ramana Reddy
fuente
Cuando publique un script, asegúrese de usar el formato de código para mantener el espacio en blanco. Además, ¿cuál es la pregunta real? No estoy seguro de lo que quieres decir ...
AJefferiss
2
@Arronical no es necesario, echo puede manejar palabras reservadas echo if case then do.
terdon
Para un problema similar, pero lidiando con la clasificación, consulte askubuntu.com/questions/597924/…
Joe

Respuestas:

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  

Para obtener más información acerca de la expresión regular en minúsculas de [az] y la expresión regular en mayúsculas de [AZ] en bash, consulte ¿Por qué no se distingue entre mayúsculas y minúsculas cuando nocasematch está desactivado? .

karel
fuente
66
Siguiendo con esto, en lugar de [0-9]que pueda usar [[:digit:]]. Puede encontrar más ejemplos en las clases de caracteres posix deman grep Google .
Paddy Landau
21

El problema es que el rango de caracteres en [a-z]realidad incluye las letras mayúsculas. Esto se explica en el manual de bash :

Dentro de una expresión de paréntesis, una expresión de rango consta de dos caracteres separados por un guión. Coincide con cualquier carácter individual que se clasifique entre los dos caracteres, inclusive. En la configuración regional C predeterminada, la secuencia de clasificación es el orden de los caracteres nativos; por ejemplo, '[ad]' es equivalente a '[abcd]'. En otras configuraciones regionales, la secuencia de clasificación no se especifica y '[ad]' podría ser equivalente a '[abcd]' o '[aBbCcDd]' , o podría no coincidir con ningún carácter o el conjunto de caracteres que los partidos pueden incluso ser erráticos. Para obtener la interpretación tradicional de las expresiones de paréntesis, puede usar la configuración regional 'C' estableciendo la variable de entorno LC_ALL en el valor 'C'.

Para ilustrar:

$ 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

Entonces, lo que sucede es que en su configuración regional (que no lo es C), [a-c]es en realidad [aAbBcC]. Es por eso que debería usar las clases de caracteres POSIX como lo sugiere @karel en su lugar.

terdon
fuente
44
De manera más precisa, es necesario set LC_COLLATEa C, está bien que los otros valores de localización para ser diferente. Establecer LC_COLLATEcualquier cosa, pero Crara vez es una buena idea, pero lamentablemente Ubuntu lo hace (no es el único culpable por el momento).
Gilles 'SO- deja de ser malvado'