为什么“ls”以看似不同的顺序列出以下文件?

为什么“ls”以看似不同的顺序列出以下文件?

为什么ls以看似不同的顺序列出以下文件?

默认情况下,不会ls按我当前语言环境的字典顺序列出文件,我猜这是默认的?

$ ls
a_1  a_10  a_11  a_12

$ ls
a_10-18  a_11-18  a_1-18  a_12-18

我有alias ls='ls --color=auto'LC_COLLATE="en_US.UTF-8"

答案1

语言环境确实很复杂。目的是让非技术用户“感觉正常”。 (技术人员可以使用LANG=C它来获得那种温暖模糊的感觉。)技术定义是Unicode 标准文档,我试图在这里提炼一些内容。很高兴收到更正。

我觉得读起来很有趣语言环境是处理数据的用户的属性,而不是数据本身的属性。尽管示例字符串中使用的字符相同,但该技术文档还是用了一定的篇幅来阐明这一点,即德国用户的排序顺序与瑞典用户的排序顺序不同。

en_GB 和 en_US 语言环境设置为忽略该-字符。这些区域设置的升序排序规则非常简单:

  1. 不区分大小写
  2. 如果您有两个字符串,它们最初相同,只是其中一个较长,那么它会排在第二位。所以xyzA总是在之后xyz
  3. -除非与其他标点符号进行比较,否则某些标点符号(在这种情况下包括)将被忽略
  4. 数字在字母之前排序
  5. 数字已排序0..9
  6. 字母已排序[Aa].. [Zz](en_GB 和 en_US 并没有真正的重音符号)
  7. 对于任何给定的字母,小写字母排在大写字母之前(因此one位于 之前One,但两者都位于 之前two
  8. 标点符号已排序(但与此答案中的示例无关)

将这些规则应用于相关数据集:

a_1  a_10  a_11  a_12

这相当于a1 a10 a11 a12, 并且考虑到规则#2,我们得到a1必须在a10和之前a11。除此以外的所有内容a1都具有相同数量的字母数字字符,因此可以一致地比较它们。这给了我们a_1 a_10 a_11 a_12.

a_10-18  a_11-18  a_1-18  a_12-18

相同的规则适用,除了 #3 也适用(我们忽略标点符号)。这意味着我们可以将这些值视为a_1018 a_1118 a_118 a_1218,并按照规则 #2 和 #4 我们得到顺序a_10-18 a_11-18 a_1-18 a_12-18

以评论中的最后一个例子为例

a_10 a_10- a_100 a_101 a_10-18 a_102

适用规则 #3,然后适用规则 #2、#4。因此,我们删除(忽略)-给出 的字符a_10 a_10 a_100 a_101 a_1018 a_102,并按公共子字符串前缀然后按字符顺序对剩余部分进行排序。

(我不清楚我们是否会因为长度a_10而得到然后,或者只是因为它恰好以这种方式结束。我很想建议后者,但我希望有人能证实这一点。)a_10-

答案2

按照字典顺序,a_1位于以 开头的任何其他字符串之前a_1。由于数字在任何合理的区域设置中都按数字顺序排列,因此在任何合理的区域设置中,a_1< a_10< a_11< a_12

如果向这些字符串添加公共后缀,则顺序可能会发生变化,因为该公共后缀可能会排序在中间的某个位置。在第二个示例中,有四个字符串以公共前缀 开头,a_1并分别带有后缀0-181-18和。在 C 语言环境中,字符串是按照严格的字典顺序进行比较的;出现在数字之前,因此先出现:< < < 。但大多数其他语言环境更为复杂。特别是,除非作为最后手段,否则标点符号会被忽略。因此,要比较字符串 < < < ,首先比较无标点符号字符串, ;第二个数字的顺序是< < < ,中间两个字符串的第三个数字的顺序是< 。如果添加仅标点符号不同的字符串,则不同的标点符号将决定其排序方式,例如< < <-182-18--18a_10-18a_11-18a_1-18a_12-18a_10-18a_11-18a_1-18a_12-18a1018a1118 a118 a1218011218a_10-18a_1-118a_11-18a_12-18

我的回答中的解释很简单。可以有两次以上的传递,以处理标点符号之类的问题。这重症监护病房用户指南有一个相当详细的解释(但即使如此,也没有处理对书籍索引等内容进行排序的所有微妙之处)。

相关内容