Linux 命令行(书 - 页数 47)说:
...您必须非常小心它们[字符范围],因为除非正确配置,否则它们不会产生预期的结果。目前,您应该避免使用它们并使用字符类。
除此之外,这本书没有给出任何理由。
问题 - 1:那么,究竟为什么应该字符类(例如,,,[:alnum:]
等)优先于[:alpha:]
[:digit:]
字符范围(例如,,,[a-z]
等)?[A-Z]
[0-9]
问题2:代表[:alpha:]
, [a-z]
,[A-Z]
和其他语言的大写和小写字母? 同样,是否[:digit:]
也包括来自其他语言的数字?如果它们匹配的话。
(我知道有两个问题,但在本例中,它们几乎是相互关联的,IMO。)
答案1
根据bash
联机帮助页,LC_COLLATE
环境变量会影响字符范围,正如 Hauke Laging 的回答一样:
LC_COLLATE 此变量确定对路径名扩展结果进行排序时使用的排序规则,并确定范围表达式、等价类以及路径名扩展和模式匹配中的排序序列的行为。
另一方面,LC_CTYPE
影响字符类别:
LC_CTYPE该变量确定路径名扩展和模式匹配中字符的解释以及字符类的行为。
这意味着什么两个都如果您在英语、从左到右、拉丁字母、阿拉伯数字的环境中思考,那么这些情况可能会出现问题。
如果您真的很合适,并且/或者正在为多语言环境编写脚本,那么最好确保您在匹配文件时知道您的语言环境变量是什么,或者确保您在一个完全通用的方式。
但是,除非您学过语言学,否则很难预见某些情况。
但是,我不知道使用拉丁语的语言环境会改变命令字母,所以 [az] 可以。那里是拉丁字母的扩展,以不同的方式整理连字和变音符号。不过,这里有一个小实验:
mkdir /tmp/test
cd /tmp/test
export LC_CTYPE=de_DE.UTF-8
export LC_COLLATE=de_DE.UTF-8
touch Grüßen
ls G* # This says ‘Grüßen’
ls *[a-z]en # This says nothing!
ls *[a-zß]en # This says ‘Grüßen’
ls Gr[a-z]*en # This says nothing!
这很有趣:至少对于德语来说,像 ü 这样的变音符号和像 ß 这样的连字都不会折叠成拉丁字符。 (要么那样,要么我搞砸了区域设置更改!)
当然,这可能对您不利,如果您尝试查找以字母开头的文件名,请使用[a-z]*
并将其应用于以“Ä”开头的文件。
答案2
至少在 OS X 上使用 bash 4.2 时,UTF-8 语言环境似乎使用 ASCII 排序规则,但 ISO 8859-1 语言环境在某些情况下不使用:
$ LC_ALL=en_US.UTF-8 tr A-C 1-9 <<< B
2
$ LC_ALL=en_US.ISO8859-1 tr A-C 1-9 <<< B
6
$ LC_ALL=en_US.UTF-8 grep [A-Z] <<< ä
$ LC_ALL=en_US.ISO8859-1 grep [A-Z] <<< ä
ä
在某些环境中,UTF-8 语言环境还使用不同的排序规则。
[:upper:] 和 [:lower:] 在许多语言环境中还包含非 ASCII 字符。如果您只想匹配 ASCII 字符,请使用如下内容:
LC_ALL=C tr a-zA-Z n-za-mN-ZA-M
如果 LC_ALL 已设置为其他值,则 LC_COLLATE=C 或 LANG=C 将不起作用。
答案3
“其他语言”,就是这样。不同的区域设置可能有不同的排序顺序。因此从理论上讲,这可能a-z
与另一个区域设置不同。如果您想要匹配所有内容,范围就会变得困难。第一个字符是什么,最后一个字符是什么?
openSUSE 的人在检查用户名/密码时对此非常偏执,他们这样做:[abcdefghi...]
我从未想过其他语言/字符集中的数字。有趣的一点。