LC_COLLATE 是否(应该)影响字符范围?

LC_COLLATE 是否(应该)影响字符范围?

整理order throughLC_COLLATE不仅定义了单个字符的排序顺序,还定义了字符范围的含义。或者确实如此?考虑以下片段:

unset LANGUAGE LC_ALL
echo B | LC_COLLATE=en_US grep '[a-z]'

直观上,Bis 不在 中[a-z],所以这不应该输出任何内容。这就是 Ubuntu 8.04 或 10.04 上发生的情况。但在某些运行 Debian lenny 或挤压的机器上,B会发现,因为范围包括排序规则中和a-z之间的所有内容,包括大写字母到。azBZ

所有测试的系统都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给定相应语言环境的合理定义。我无法解释为什么这有时对您不起作用,但如果我在正确安装和配置的非古老系统上遇到这种情况,我会感到非常惊讶。

相关内容