gnu sort中的--general-numeric-sort和--numeric-sort选项有什么区别


113

sort提供两种数值排序。这是从手册页:

   -g, --general-numeric-sort
          compare according to general numerical value

   -n, --numeric-sort
          compare according to string numerical value

有什么不同?


17
请注意,的完整文档sort不是man页面而是info页面(info sort)。
a3nm 2012年

Answers:


85

一般数字排序将数字作为浮点数进行比较,这可以采用科学记数法,例如1.234E10,但速度较慢并且容易出现舍入错误(1.2345678可能在1.2345679之后),数字排序只是一种常规的字母排序,知道10在9之后。

参见http://www.gnu.org/software/coreutils/manual/html_node/sort-invocation.html

'-g''--general-numeric-sort''--sort = general-numeric'使用标准C函数strtod进行数字排序,将每行的前缀转换为双精度浮点数。这允许以科学计数法指定浮点数,例如1.0e-34和10e100。LC_NUMERIC语言环境确定小数点字符。不要报告上溢,下溢或转换错误。使用以下整理顺序:不以数字开头的行(均视为相等)。NaN(IEEE浮点运算中的“非数字”值)以一致但与机器相关的顺序排列。负无穷大。有限数字按升序排列(-0和+0相等)。再加上无限。

仅在没有其他选择时才使用此选项。它比--numeric-sort(-n)慢得多,并且转换为浮点数时可能会丢失信息。

'-n''--numeric-sort''--sort = numeric'按数字排序。数字以每行开头,由可选的空格,可选的“-”符号以及可能由数千个分隔符分隔的零个或多个数字组成,并可选地后面跟一个小数点字符和零个或多个数字。空数字将被视为“ 0”。LC_NUMERIC语言环境指定小数点字符和千位分隔符。默认情况下,空格是空格或制表符,但是LC_CTYPE语言环境可以更改此设置。

比较准确;没有舍入错误。

前导“ +”或指数符号均无法识别。要对这些字符串进行数字比较,请使用--general-numeric-sort(-g)选项。


2
谢谢。奇怪的是,手册和信息页面中没有此页面。我也不知道gnu.org/software/coreutils/manual/html_node/index.html
特伦顿

6
这些东西对我不起作用。我正在对第三列的文件进行排序,其内容类似于R1 R2 R10 R15。使用-k3.2n或者-k3.2g,它R10在之前进行排序R2。排序是字典式的,不是数字式的。我希望它将第二个字符开始的字段视为一个数字。
哈兹2012年

6
@Kaz:sort的主要规格。是真正的拜占庭式-简称:字段前面的空格被认为是字段一部分,所以为char。索引1指向字段前面的(第一个)空白,而不是字段的实际第一个字符。后缀字符。用指数b来解决这个问题,即:-k 3.2bn,3(注意,全球 -b选项确实没有在这种情况下工作)。还要注意添加的,3,它确保仅使用第三个字段-不使用第二个字段索引,则使用整行其余部分
mklement0

11

您应该注意自己的语言环境。例如,您可能打算对浮点数进行排序(例如2.2),而您的语言环境可能希望使用逗号(例如2,2)。

本论坛所报道,使用-n或-g标志可能会导致错误的结果。

就我而言,我使用:

LC_ALL=C sort -k 6,6n file

为了对包含以下内容的第六列进行排序:

2.5
3.7
1.4

为了获得

1.4
2.5
3.7

2
即使使用LANG = C,我也无法-n将逗号识别为千位分隔符-“ 1,000”被视为与“ 1”相同。
Scott

1
那应该是LC_ALL = C。
Stuart P. Bentley

@Scott:确实,没有识别出数千个分隔符:sort使用最长前缀逻辑:使用了它识别为数字的行/键的最长部分;在.用作基数字符的语言环境中,它将在处停止读取,
mklement0 2015年

@ StuartP.Bentley:LC_ALL=C确实是最可靠的选择;但是,如果LC_ALL碰巧没有下注,它LANG=C也会起作用。
mklement0 2015年

1
很好,但不仅LANG=C sort -k 6,6n file简单,而且还可以将环境变量的设置本地化LANG为特定命令。
mklement0 2015年

0

除了提及-g允许科学表示的可接受答案外,我还要显示最有可能导致不良行为的部分。

-g

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=en_US.UTF-8 sort -g myfile
baa
--inf
--inf  
--inf- 
--inf--
--inf-a
--nnf
nnf--
   nnn  
tnan
zoo
   naN
Nana
nani lol
-inf
-inf--
-11
-2
-1
1
+1
2
+2
0xa
11
+11
inf

请看zoo这里的三件重要的事情:

  • 行的开头是NAN(例如Nananani lol)或-INF(单破折号,不是--INF)移动到结尾但在数字之前。而INF移动到数字后的最后一位是因为这意味着无穷大

  • NANINF以及-INF不区分大小写

  • 线总是从任一侧忽略空白NANINF-INF(不管LC_CTYPE)。其他字母可能会从两侧忽略空格,具体取决于语言环境LC_COLLATE(例如,LC_COLLATE=fr_FR.UTF-8忽略但LC_COLLATE=us_EN.UTF-8不能忽略)。

因此,如果您要对任意字母数字进行排序,则可能不需要-g。如果您确实需要与之进行科学的符号比较-g,那么您可能希望提取字母和数字数据并分别进行比较

如果您只需要普通数字(例如1, -1)排序,并且觉得0x/E/+ sorting不重要,则只需使用-n足够:

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=en_US.UTF-8 sort -n myfile
-1000
-22
-13
-11
-010
-10
-5
-2
-1
-0.2
-0.12
-0.11
-0.1
0x1
0x11
0xb
+1
+11
+2
-a
-aa
--aa
-aaa
-b
baa
BAA
bbb
+ignore
inf
-inf
--inf
--inf  
--inf- 
--inf--
-inf--
--inf-a
   naN
Nana
nani lol
--nnf
nnf--
   nnn  
None         
uum
Zero cool
-zzz
1
1.1
1.234E10
5
11

任一-g或者-n,要注意的区域效应。您可能需要指定LC_NUMERICas us_EN.UTF-8 以避免fr_FR.UTF-8 -浮点数排序失败

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=fr_FR.UTF-8 sort -n myfile
-10
-5
-2
-1
-1.1
-1.2
-0.1
-0.11
-0.12
-0.2
-a
+b
middle
-wwe
+zoo
1
1.1

LC_NUMERIC=en_US.UTF-8

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=en_US.UTF-8 sort -n myfile
-10
-5
-2
-1.2
-1.1
-1
-0.2
-0.12
-0.11
-0.1
-a
+b
middle
-wwe
+zoo
1
1.1

LC_NUMERIC=us_EN.UTF-8到组+|-|spacealpha

$ LC_COLLATE=fr_FR.UTF-8 LC_NUMERIC=us_EN.UTF-8 sort -n myfile
-0.1
    a
    b
 a
 b
+b
+zoo
-a
-wwe
middle
1

您可能想在使用locale时指定sort是否要编写可移植脚本。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.