【问题标题】:What's the difference between --general-numeric-sort and --numeric-sort options in gnu sortgnu排序中--general-numeric-sort和--numeric-sort选项有什么区别
【发布时间】:2020-04-30 15:56:43
【问题描述】:

sort 提供两种数字排序。这是来自手册页:

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

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

有什么区别?

【问题讨论】:

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

标签: unix sorting


【解决方案1】:

一般数字排序将数字作为浮点数进行比较,这允许科学记数法,例如 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 语言环境 确定小数点 特点。不报告溢出, 下溢或转换错误。利用 以下整理顺序: 不以数字开头的行 (都被认为是平等的)。钠离子 (“非数字”值,在 IEEE 浮点运算)在一个 一致但依赖于机器 命令。负无穷大。有限 按数字升序排列的数字 (与 -0 和 +0 相等)。加 无穷。

只有在没有 选择;它比 --numeric-sort (-n) 转换为 浮点。

‘-n’ ‘--numeric-sort’ ‘--sort=numeric’ 按数字排序。号码开始 每行包含可选 空格、可选的“-”号和零 或更多数字可能由 千位分隔符,可选 后跟一个小数点字符 和零个或多个数字。一个空 数字被视为“0”。这 LC_NUMERIC 语言环境指定 小数点字符和千位 分隔器。默认情况下,空白是 空格或制表符,但 LC_CTYPE 语言环境可以改变这一点。

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

既不是前导“+”也不是指数 符号被识别。比较 这样的字符串数字,使用 --general-numeric-sort (-g) 选项。

【讨论】:

  • 谢谢。奇怪的是 man 和 info 页面中没有这个。我也不知道gnu.org/software/coreutils/manual/html_node/index.html
  • 这东西不适合我。我正在对一个文件进行排序,其中第三列的内容类似于 R1 R2 R10 R15。使用-k3.2n-k3.2g,它会将R10 排序在R2 之前。排序是字典顺序的,而不是数字的。我希望它将从第二个字符开始的字段视为数字。
  • @Kaz: sort 的关键规格。是真正的拜占庭式 - 简而言之:字段前面的 空白 被认为是 字段的一部分,因此 char. index 1 指向字段前面的(第一个)空白,而不是字段的实际第一个字符。为字符添加后缀。用b 索引来解决这个问题,即:-k 3.2bn,3(注意global -b 选项在这种情况下not 起作用)。还要注意添加的,3,它确保只使用第三个字段 - 如果没有第二个字段索引,则使用整行的其余部分
【解决方案2】:

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

正如this forum 中所报告的,使用 -n 或 -g 标志可能会得到错误的结果。

就我而言,我使用:

LC_ALL=C sort -k 6,6n file

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

2.5
3.7
1.4

为了获得

1.4
2.5
3.7

【讨论】:

  • 即使使用 LANG=C,我也无法让 -n 将逗号识别为千位分隔符——“1,000”被视为与“1”相同。
  • 应该是 LC_ALL=C。
  • @Scott:确实,千位分隔符无法识别:sort 使用 longest-prefix 逻辑:使用它识别为数字的行/键的最长部分;在使用. 作为基数字符的语言环境中,它将在, 处停止读取。
  • @StuartP.Bentley:LC_ALL=C 确实是最强大的选择;但是,如果 LC_ALL 碰巧没有下注,LANG=C 也会起作用。
  • 好点,但LANG=C sort -k 6,6n file 既简单又本地化将环境变量LANG 设置为特定命令的效果。
【解决方案3】:

除了提到-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 移动到最后一位,因为it means infinity

  • 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_NUMERIC 指定为us_EN.UTF-8 to avoid fr_FR.UTF-8 sort - with floating number failed

$ 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

如果要编写可移植脚本,您可能希望在使用sort 时指定locale

【讨论】:

    猜你喜欢
    • 2017-03-19
    • 2016-06-03
    • 2019-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-22
    • 2010-10-20
    • 2013-04-17
    相关资源
    最近更新 更多