0

我有一个名为 a.csv 的文件。其中包含

100008,3
10000,3
100010,5
100010,4
10001,6
100021,7

运行此命令后sort -k1 -d -t "," a.csv

结果是

10000,3
100008,3
100010,4
100010,5
10001,6
100021,7

这是出乎意料的,因为10001 should come first than 100010

试图理解为什么这会发生很久。但无法得到任何答案。

$ sort --version
sort (GNU coreutils) 8.13
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Mike Haertel and Paul Eggert.
4

5 回答 5

2

其他一些响应假设这是一个数字排序与字典排序问题。不是,因为即使按字母顺序排序问题中给出的输出也不正确。

答案

要获得正确的排序,您需要更改-k1-k1,1

$ sort -k1,1 -d -t "," a.csv
10000,3
100008,3
10001,6
100010,4
100010,5
100021,7

原因

-k选项采用两个数字,开始和结束字段进行排序(即-ks,e开始se结束的位置)。默认情况下,结束字段是行尾。因此,-k1与根本不提供选项相同-k。为了证明这一点,比较:

$ printf "1,a,1\n2,aa,2\n" | sort -k2 -t,
1,a,1
2,aa,2

和:

$ printf "1~a~1\n2~aa~2\n" | sort -k2 -t~
2~aa~2
1~a~1

第一个在 ASCII 之前排序a,1aa,2而第二个aa~2a~1since 之前排序,在 ASCII 中是,< a< ~

因此,为了获得所需的行为,我们需要对一个字段进行排序。在您的情况下,这意味着使用 1 作为开始和结束字段,因此您指定-k1,1. 如果您尝试上面的两个示例,-k2,2而不是-k2,您会发现在两种情况下都得到相同(正确)的排序。

非常感谢 coreutils 邮件列表中的 Eric 和 Assaf 指出这一点。

于 2015-12-07T13:35:55.447 回答
2

您还没有在排序中发现错误。您的使用错误是您使用了“-k1”(“将密钥设置为通过行尾的第一个字段”)而不是“-k1,1”(“将密钥设置为仅使用第一个字段”)。如果您使用 GNU 排序, --debug 选项将显示您的区别。只要键超出单个字段,定界符就包含在键中。

于 2015-12-07T16:52:44.187 回答
0

它按字母排序,而不是按数字排序,所以“,”在“0”之前,即更像字典

于 2015-12-07T13:30:24.433 回答
0

-d选项适用于--dictionary-order

-d, --dictionary-order 只考虑空格和字母数字字符

但我认为你想使用-n( --numeric-sort) 代替:

-n, --numeric-sort 根据字符串数值进行比较

因此,将您的命令更改为如下所示:

sort -k1 -n -t "," a.csv

http://man7.org/linux/man-pages/man1/sort.1.html

于 2015-12-07T13:34:21.590 回答
0

排序是按字母顺序排列的,而不是数字的。将选项列表中的 -d 替换为 -n 以进行数字排序。

于 2015-12-07T13:39:09.850 回答