[[:upper:]] 和 [:upper:] (bash) 有什么区别?

What's the difference between [[:upper:]] and [:upper:] (bash)?

所以我在 macOS High Sierra 10.13.6 下使用 bash 3.2.57(1)-release,我正在尝试编写一个需要不区分大小写输入的 bash 脚本。我读到使用 tr "[:upper:]" "[:lower:]" <<< "$(echo AaBbCcDd)" 会将整个字符串转换为小写,它确实如此。但是,我在别处读到使用 '[[:UPPER:]]''[[:LOWER:]]' 代替。这些似乎仍然有效,但它让我想知道,这两者之间有什么区别吗?

在正则表达式中,[[:upper:]]表示“任何大写字母”。但这是更一般机制的一个实例。外括号 […] 和内括号冒号 [:…:] 具有不同的含义。外括号包围着一个 字符集 。在字符集中,您可以使用方括号-冒号语法使用单个字符、范围如 2-9 字符 类。例如,正则表达式 [2-9_[:upper:]] 匹配任何大写字母或下划线或 2 到 9 之间的数字。

tr 替换单个字符,而不是正则表达式。 (还有另一个替代正则表达式的工具:sed。)它的参数是一个字符集,即你放在括号内的内容。

tr '2-9_[:upper:]' 'X'

相当于

sed 's/[2-9_[:upper:]]/X/g'

你可以这样写tr '[[:upper:]]' '[[:lower:]]',和tr '[:upper:]' '[:lower:]'一样的效果。但这并不是因为外括号有任何特殊含义。那是因为您要用 [ 替换 [,用相应的小写字母替换大写字母,用 ] 替换 ]。自己替换括号没有效果。

(顺便说一句,bash 4 有一个内置的大小写转换机制:all_uppercase=${var^^}; all_lowercase=${var,,}。但是bash 3 中不存在这个,这是Apple 提供的在 macOS 上。要获得 bash 4,您需要第三方发行版,例如 Brew。)