下面的代码片段发生了什么?我没有得到预期的输出。
我认为这是一个错误,但它发生在 2 个不同的程序(uniq 和 sort)中,所以我怀疑这与……好吧,我不知道是什么……因此就有了这个问题。
前 3 个(共 4 个)示例有效,但第 4 个示例失败!
我希望所有角色都有相同的行为。
IE。打印出 2 行(从 3 行输入中)...但在第四种情况下,我只得到 1 行(对于 和sort -u
)uniq
;两条相同的林就消失了!
我已将输出 '\n' 转换为空格以保持视图的紧凑性。
我在用着独特的和种类从 (GNU coreutils) 7.4 ...在 Ubuntu 10.04.3 LTS 桌面上运行。
剧本:
{
locale -k LC_COLLATE
echo
for c1 in x 〼 ;do
for c2 in z 〇 ;do
echo -n "asis : "; echo -e "$c1\n$c2\n$c2" |tr '\n' ' ';echo
echo -n "uniq : "; echo -e "$c1\n$c2\n$c2" |uniq |tr '\n' ' ';echo
echo -n "sort -u: "; echo -e "$c1\n$c2\n$c2" |sort -u |tr '\n' ' ';echo
echo
done
echo
done
}
输出:
collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=2081
collate-codeset="UTF-8"
asis : x z z
uniq : x z
sort -u: x z
asis : x 〇 〇
uniq : x 〇
sort -u: 〇 x
asis : 〼 z z
uniq : 〼 z
sort -u: 〼 z
asis : 〼 〇 〇
uniq : 〼
sort -u: 〼
# In the last example (of 4) where did the '〇' go? .. U+3007 IDEOGRAPHIC NUMBER ZERO
#
答案1
简短版本:排序规则在命令行实用程序中实际上不起作用。
更长的版本:比较两个字符串的底层函数是strcoll
。描述不是很有帮助,但概念性的操作方法是将两个字符串转换为规范形式,然后比较这两个规范形式。功能strxfrm
构造了这个规范形式。
让我们观察一些字符串的规范形式(使用 GNU libc,在 Debian squeeze 下):
$ export LC_ALL=en_US.UTF-8
$ perl -C255 -MPOSIX -le 'print "$_ ", unpack("h*", strxfrm($_)) foreach @ARGV' b a A à 〼 〇
b d010801020
a c010801020
A c010801090
à 101010102c6b
〼 101010102c6b102c6b102c6b
〇 101010102c6b102c6b102c6b
正如你所看到的,〼和〇具有相同的规范形式。我认为这是因为这些字符没有在en_US.UTF-8
语言环境的排序规则表中提及。然而,它们出现在日语语言环境中。
$ export LC_ALL=ja_JP.UTF-8
$ perl -C255 -MPOSIX -le 'print "$_ ", unpack("h*", strxfrm($_)) foreach @ARGV' 〼 〇
〼 303030
〇 3c9b
语言环境数据的源代码(在 Debian squeeze 中)位于 中/usr/share/i18n/locales/en_US
,其中包括/usr/share/i18n/locales/iso14651_t1_common
.该文件没有U3007
or的条目U303C
,也不包含在我能找到的任何范围内。
我不熟悉建立排序规则的规则,但据我了解,相关的措辞是
符号 UNDEFINED 应解释为包括未明确指定或通过省略号指定的所有编码字符集值。 (…) 如果未指定 UNDEFINED 符号,并且当前编码字符集包含本节中未指定的字符,则实用程序应发出警告消息并将此类字符放置在字符排序顺序的末尾。
看起来 Glibc 会忽略未指定的字符。我不知道我对 POSIX 规范的理解是否存在缺陷,是否遗漏了 Glibc 语言环境定义中的某些内容,或者 Glibc 语言环境编译器中是否存在错误。
答案2
要“安全”地使用sort
Unicode 字符串,也许可以看看msort
:
[...] Msort 在选择关键字段、更多比较类型、在不同键上使用来自不同语言环境的排序规则的能力、处理非西方数字系统中的数字的能力以及缺乏的各种其他选项方面提供了更大的灵活性在 GNU 排序和 BSD 排序中。 msort 可以理解 Unicode,而 GNU 排序和 BSD 排序则不能。 [...]