按数字排序

use*_*221 7 sort

我有一个名为data的文件,其内容是

id,col1,col2
0,-0.3479417882673812,0.5664382596767175
1,-0.26800930980980764,0.2952025161991604
2,-0.4159790791116641,-1.3375045524610152
3,-0.7859665489205871,-0.6428101880909471
4,-1.3922759043388822,-1.676262144826317
5,-1.2471867496427498,-0.4912119581361516
6,1.443385383041667,1.6974039491263593
7,-2.058899802821969,2.0607628464079917
8,-0.10641338441541626,0.035929568275064216
9,-0.517273684861199,-0.6184800988804992
10,-0.9934859021679552,1.0577312348984502
11,0.5923834706792905,-0.6693757541250825
12,0.8657741917554445,-0.6876271057571398
13,-1.2061097548360489,-0.7402582563022937
14,0.78768021182158,-0.38607117005262315
Run Code Online (Sandbox Code Playgroud)

-n在第一列上按数字 ( )排序给出

$ sort -nk1 -t"," data
0,-0.3479417882673812,0.5664382596767175
id,col1,col2
1,-0.26800930980980764,0.2952025161991604
2,-0.4159790791116641,-1.3375045524610152
3,-0.7859665489205871,-0.6428101880909471
4,-1.3922759043388822,-1.676262144826317
5,-1.2471867496427498,-0.4912119581361516
7,-2.058899802821969,2.0607628464079917
8,-0.10641338441541626,0.035929568275064216
9,-0.517273684861199,-0.6184800988804992
10,-0.9934859021679552,1.0577312348984502
13,-1.2061097548360489,-0.7402582563022937
6,1.443385383041667,1.6974039491263593
11,0.5923834706792905,-0.6693757541250825
12,0.8657741917554445,-0.6876271057571398
14,0.78768021182158,-0.38607117005262315
Run Code Online (Sandbox Code Playgroud)

这对我来说绝对奇怪。我在-n应该是数字排序的手册页中读到了。为什么id要放在数字之间?它是如何,10大于9,但比小6,而同时11大于它们呢?

-g,因为我想,似乎工作(和我认为是自然的),但是这个-n选项完全脱离了我。这是关于什么的?我认为它可能与语言环境有关,但是一旦我将分隔符指定为 is ,,我认为这无法解释它。

Sté*_*las 19

TL; 博士

使用sort -nk1,1 -t,或以其他方式与-k1对整行进行排序,其中,在数字中被丢弃,因为它被解释为千位分隔符。

细节

在英语语言环境中,,是千位分隔符,sort在数字的整数部分被忽略。

换句话说,在英语语言环境或,千位分隔符的任何语言环境中(请参阅 的输出locale thousands_sep),当sort -n看到11,000,000它时,它不会看到11数字后跟一些被忽略的垃圾,而是11000000数字。同样11,0不是11但是110

现在(这是很多人绊倒的东西), -k1定义一个从第一个字段开始的键,但由于您没有指定它在哪里停止,在行尾结束,因此排序键是整行,即是默认值。

所以sort -nk1 -t,完全一样sort -n.

随着,忽视的一个千个分隔符,您输入sort实际上是分选这些数字:

0
1
2
3
4
5
61.4433853830416671
7
8
9
10
110.5923834706792905
120.8657741917554445
13
140.78768021182158
Run Code Online (Sandbox Code Playgroud)

所以它不是6vs 10vs 11,而是61.4433853830416671vs 10vs 110.5923834706792905

在这里,你想要:

sort -nk1,1 -t,
Run Code Online (Sandbox Code Playgroud)

,仅对第一个分隔字段进行排序。-k1,1定义从第一个字段的开头开始并在第一个字段的结尾结束的排序键。

您还可以sort -n在 C 语言环境中使用,其中,既不是十进制基数也不是千位分隔符(并且.是十进制基数):

LC_ALL=C sort -n
Run Code Online (Sandbox Code Playgroud)

sort -g工作方式不同,因为sortthen 用于strtold()将键解释为数字并且strtold()不识别千位分隔符。

id标题行而言,在数字比较中,这id...被解释为0在那里看不到数字。它在以 开头的行之后0排序,因为当两个记录排序相同时(这里是-n在数字比较中)sort进行最后的比较,这是对整行的词法比较(并0在 之前排序i)。

随着一些sort实现方式中,不得已而为之的比较可以被禁用-s。这里LC_ALL=C sort -sn会将id行放在首位,但这只是因为输入中没有负键(id(再次数字为 0)仍会在 之后排序-1)。如果要从排序中排除第一行,可以执行以下操作:

(head -n1; LC_ALL=C sort -n) < file
Run Code Online (Sandbox Code Playgroud)