5

即使我指定了分隔符,unix 数字排序也会给出奇怪的结果。

$ cat example.csv  # here's a small example
58,1.49270399401
59,0.000192136419373
59,0.00182092924724
59,1.49270399401
60,0.00182092924724
60,1.49270399401
12,13.080339685
12,14.1531049905
12,26.7613447051
12,50.4592437035

$ cat example.csv | sort -n --field-separator=,
58,1.49270399401
59,0.000192136419373
59,0.00182092924724
59,1.49270399401
60,0.00182092924724
60,1.49270399401
12,13.080339685
12,14.1531049905
12,26.7613447051
12,50.4592437035

对于此示例,无论您是否指定分隔符,sort 都会给出相同的结果。我知道如果我设置LC_ALL=C然后排序开始再次给出预期的行为。但我不明白为什么如下所示的默认环境设置会发生这种情况。

$ locale
LANG="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_CTYPE="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_ALL=

我已经阅读了许多其他问题(例如hereherehere)如何避免这种行为,但是,这种行为仍然非常奇怪和不可预测,并让我心痛了一个星期。有人可以解释为什么在 Mac OS X (10.8.5) 上使用默认环境设置排序会这样吗?换句话说: sort 正在做什么(将局部变量设置为 en_US.UTF-8)以获得该结果?

我在用着

 sort 5.93                        November 2005

 $ type sort
 sort is /usr/bin/sort

更新

我已经在 gnu-coreutils 列表中讨论过这个问题,现在明白了为什么使用英语 unicode 默认语言环境设置排序会给出它所做的输出。因为在英文 unicode 中,逗号字符“,”被认为是一个数字(以便允许逗号作为千位(或例如数百位)分隔符),并且 sort 在解释一行时默认为“贪婪”,它读取示例数字大约

581.491...
590.000...
590.001...
591.492...
600.001...
601.492...
1213.08...
1214.15...
1226.76...
1250.45...

虽然这不是我的本意,但为了得到我想要的实际结果,chepner 是正确的,但我需要指定我希望排序仅在第一个字段上键入。sort 默认将更多的行解释为键,而不仅仅是第一个字段作为键。

这种排序行为已在 gnu-coreutil 的FAQ中讨论过,并且在排序的 POSIX 描述中进一步指定。

因此,正如gnu-coreutil 列表中的 Eric Blake 所说,如果字段分隔符也是数字(逗号是),那么“如果没有 -k 来停止,[字段分隔符] 既可以作为分隔符和一个数字字符 - 您正在对跨越多个字段的数字进行排序。”

4

3 回答 3

7

我不确定这是否完全正确,但很接近。

sort -n -t,将尝试按给定键进行数字排序。在这种情况下,键是一个由整数和浮点数组成的元组。这样的元组不能按数字排序。

如果您明确指定要排序的单个键

sort -k1,1n -k2,2n -t,

它应该工作。现在您明确告诉sort首先对第一个字段(数字)排序,然后对第二个字段(也是数字)进行排序。

我怀疑-n只有当输入的每一行都包含一个数值时,它才可用作全局选项。否则,您需要将该-n选项与该-k选项结合使用以准确指定哪些字段是数字。

于 2013-10-07T16:09:48.467 回答
1

使用 sort --debug 找出发生了什么。我用它来详细解释您的问题: http: //lists.gnu.org/archive/html/coreutils/2013-10/msg00004.html

于 2013-10-08T23:05:30.680 回答
0

如果你使用

cat example.csv | sort

代替

cat example.csv | sort -n --field-separator=,

那么它会给出正确的输出。使用此命令,希望对您有所帮助。

注意:我用“sort (GNU coreutils) 7.4”测试过

于 2013-10-07T16:01:23.300 回答