我使用的是 Ubuntu 18.04 和默认的 coreutils。我注意到该命令的一个特殊行为sort
,我不确定如何解释。
考虑以下命令:
$ cat <<EOF | sort
0-
01-
EOF
0-
01-
此输出是有意义的,因为-
ASCII 值小于预期值1
,因此此输出是预期的。
但是,如果我在最后多加一个字符:
$ cat <<EOF | sort
0-T
01-T
EOF
01-T
0-T
这个输出对我来说没有任何意义,因为我认为0-T
应该放在第一位。为什么会出现这种情况。我在这里缺少什么?我的期望是错误的吗?
答案1
这取决于您所在区域的排序规则。
整理顺序是针对每个区域设置的一组规则,允许对重音字母进行排序(例如,在西班牙语中将ñ
出现在之后n
但之前o
)。
但事实并非如此,排序规则还规定了排序时要忽略哪些字符。对于语言环境“C”,会考虑所有字符,但对于“en_US”,破折号 (U002D) 会被忽略,对于大多数其他语言环境,因为它们继承了 iso14651_t1_common 的定义(在 /usr/share/ i18n/locales/ 在某些发行版中)。
因此,第一个文件的排序不会造成问题,因为当您忽略破折号时,您最终会得到简单的字母比较:
-- ignore dashes --> -- sort -->
0- 0 0
01- 01 01
当你添加“T”时,事情发生了变化,为什么?因为现在,如果您忽略破折号,则必须比较“1”和“T”(第一个字符相同),并且“1”位于“T”之前:
-- ignore dashes --> -- sort -->
0-T 0T 01T
01-T 01T 0T
因此,最好始终确保使用“C”的规则,在排序时使用 LC_COLLATE=C。
在你的情况下:
$ cat <<EOF | LC_COLLATE=C sort
0-T
01-T
EOF
产量:
0-T
01-T
正如你所料。
答案2
是的,这可能看起来很烦人。 (默认语言环境为 en_US.UTF-8)
$ printf '%s\n' 1 1- 1-a 11- 11-a | sort
1
1-
11-
11-a
1-a
原因是 已-
分配no weight
给整理顺序。
类似于 a"
应该做的事情:
printf '%s\n' 1 \"1\" 1- \"1-\" 1-a \"1-a\" 11- \"11-\" 11-a \"11-a\" | sort
"1"
"1-"
1
1-
"11-"
11-
"11-a"
11-a
"1-a"
1-a
正如您在上面看到的,所有 1 都排序在一起,11
也全部。问题是它的1-a
排序1a
比其他任何东西都更像:
printf '%s\n' 1-a 1-b 1-c 1a 1b 1c| sort
1-a
1a
1-b
1b
1-c
1c
无论标点(-
、"
和;
其他)是否应该包含在排序规则中是有争议的。普遍的观点是不应该(在非 ASCII 语言环境中)。
这常见的大多数拉丁语言的文件是/usr/share/i18n/locales/iso14651_t1_common
.在该文件中HYPHEN-MINUS
(是的,用外行术语来说,我们称之为破折号。Unicode U-002D)整理顺序设置为:
<U002D> IGNORE;IGNORE;IGNORE;<U002D> % HYPHEN-MINUS
也就是说,忽略前三个级别的整理。