shell 脚本中的区分大小写

Ram*_*ddy 10 bash scripts

考虑这个 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
Run Code Online (Sandbox Code Playgroud)

如果我输入“a”,输出是小写字母,“A”也是一样的......我该如何克服这个问题?

ter*_*don 21

问题是字符范围[a-z]实际上包括大写字母。这在bash 手册中有解释:

在括号表达式中,范围表达式由用连字符分隔的两个字符组成。它匹配在两个字符之间排序的任何单个字符,包括两个字符。在默认的 C 语言环境中,排序顺序是本机字符顺序;例如,“[ad]”等同于“[abcd]”。在其他语言环境中,未指定排序顺序,并且 '[ad]' 可能等效于 '[abcd]' 或 '[aBbCcDd]',或者它可能无法匹配任何字符,或它的字符集比赛甚至可能不稳定。要获得括号表达式的传统解释,您可以通过将 LC_ALL 环境变量设置为值“C”来使用“C”语言环境。

为了显示:

$ 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
Run Code Online (Sandbox Code Playgroud)

因此,在您的语言环境中(不是C),[a-c]实际上是[aAbBcC]. 这就是为什么您应该使用@karel建议的 POSIX 字符类的原因。

  • 更准确地说,您需要将 `LC_COLLATE` 设置为 `C`,其他语言环境设置不同也可以。将 `LC_COLLATE` 设置为除 `C` 之外的任何内容很少是一个好主意,但遗憾的是 Ubuntu 做到了(到目前为止,它并不是唯一的罪魁祸首)。 (4认同)

kar*_*rel 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  
Run Code Online (Sandbox Code Playgroud)

有关bash中[az]的小写正则表达式和[AZ]的大写正则表达式的更多信息,请参阅为什么在 nocasematch 关闭时 case 语句不区分大小写?.

  • 继此之后,您可以使用 `[[:digit:]]` 代替 `[0-9]`。您可以在 `man grep` 或 Google **posix character classes** 中找到更多示例。 (6认同)