某种奇怪的行为

某种奇怪的行为

我使用的是 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

也就是说,忽略前三个级别的整理。

相关内容