![LC_COLLATE 是否(应该)影响字符范围?](https://linux22.com/image/2793/LC_COLLATE%20%E6%98%AF%E5%90%A6%EF%BC%88%E5%BA%94%E8%AF%A5%EF%BC%89%E5%BD%B1%E5%93%8D%E5%AD%97%E7%AC%A6%E8%8C%83%E5%9B%B4%EF%BC%9F.png)
整理order throughLC_COLLATE
不仅定义了单个字符的排序顺序,还定义了字符范围的含义。或者确实如此?考虑以下片段:
unset LANGUAGE LC_ALL
echo B | LC_COLLATE=en_US grep '[a-z]'
直观上,B
is 不在 中[a-z]
,所以这不应该输出任何内容。这就是 Ubuntu 8.04 或 10.04 上发生的情况。但在某些运行 Debian lenny 或挤压的机器上,B
会发现,因为范围包括排序规则中和a-z
之间的所有内容,包括大写字母到。a
z
B
Z
所有测试的系统都en_US
生成了区域设置。我还尝试改变区域设置:在B
上面匹配的机器上,{en_{AU,CA,GB,IE,US},fr_FR,it_IT,es_ES,de_DE}{iso8859-1,iso8859-15,utf-8}
除了日语(任何可用的编码)和C
/之外,每个可用的区域设置(主要是基于拉丁语的:,还有中文区域设置)都会发生同样的情况POSIX
。
正则表达式中的字符范围意味着什么,什么时候超越 ASCII?为什么某些 Debian 安装与其他 Debian 安装和 Ubuntu 之间存在差异?其他系统如何表现?谁是对的,谁应该报告错误?
(请注意,我特别询问字符范围的行为,例如[a-z]
在en_US
语言环境中,主要是在基于 GNU libc 的系统上。我不是问如何匹配小写字母或 ASCII 小写字母。)
在两台 Debian 机器上,一台B
在[a-z]
,一台不在,输出LC_COLLATE=en_US locale -k LC_COLLATE
是
collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=1
collate-codeset="ISO-8859-1"
的输出LC_COLLATE=en_US.utf8 locale -k LC_COLLATE
是
collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=2039
collate-codeset="UTF-8"
答案1
如果您使用除C
区域设置之外的任何内容,则不应使用类似的范围,[a-z]
因为这些范围取决于区域设置,并且并不总是给出您期望的结果。除了您已经遇到的大小写问题外,某些语言环境还使用变音符号来处理字符(例如A)与基本字符相同(即A)。
相反,使用命名字符类:
echo B | grep '[[:lower:]]'
这将始终给出区域设置的正确结果。但是,您需要选择区域设置以反映输入文本和您尝试应用的测试的含义。
例如,如果您需要查找特定字节值,请使用C
始终可用的区域设置:
echo B | LANG=C grep '[a-z]'
如果这没有按预期工作,那么它确实是一个错误。
答案2
正则表达式中的范围应遵守排序规则设置。以下是相关标准:http://pubs.opengroup.org/onlinepubs/007908799/xbd/re.html(寻找“范围表达式”)。因此echo B | LC_COLLATE=en_US grep '[a-z]'
应该输出B
给定相应语言环境的合理定义。我无法解释为什么这有时对您不起作用,但如果我在正确安装和配置的非古老系统上遇到这种情况,我会感到非常惊讶。