Bash 当没有提供--stable选项时,sort-n是否可以预测地处理关系?如果有,如何解决?
在这里,两行中Bash 当没有提供--stable选项时,sort-n是否可以预测地处理关系?如果有,如何解决?,bash,sorting,language-lawyer,lexicographic,stable-sort,Bash,Sorting,Language Lawyer,Lexicographic,Stable Sort,在这里,两行中3后面的空格似乎打破了数字排序,并允许字母排序,因此11 在这里,看起来两行中的3后面的空格打破了数字排序,让字母排序开始 sort-n不是sort-n-k1,1-k2,2sort-n将整行(不是字段!)解释为一个数字,如atoi(“3 11”)给出3。然后对这些数字进行排序。因为sort\u它们(atoi(“3 11”)、atoi(“3 2”)都是未排序的,因为它们都是数字3,所以最后的比较排序开始了 最后的比较是如何完成的 其思想是,通过strcmp或类似方法(即strcoll
3
后面的空格似乎打破了数字排序,并允许字母排序,因此11
在这里,看起来两行中的3后面的空格打破了数字排序,让字母排序开始
sort-n
不是sort-n-k1,1-k2,2
sort-n
将整行(不是字段!)解释为一个数字,如atoi(“3 11”)
给出3
。然后对这些数字进行排序。因为sort\u它们(atoi(“3 11”)、atoi(“3 2”)
都是未排序的,因为它们都是数字3
,所以最后的比较排序开始了
最后的比较是如何完成的
其思想是,通过strcmp
或类似方法(即strcoll
)对整行进行比较。因为1
在2
之前,所以strcmp(“3 11”,“3 2”)
将3 11
排序为第一个。不考虑任何选项,-n
不考虑
如果有必要回答这个问题,欢迎参考源代码
实际上,GNU排序中的xmemcoll0
需要考虑排序,当未设置LC\u-COLLATE
时,memcmp
作为后备方案
我在openbsd排序中看到了一些东西,但是,如果所有键比较相等,则调用top_level_str_coll,只对整行进行排序
标准/POSIX对此有什么说明吗
如果“this”指的是稳定排序和最后的比较,那么肯定。让我们从我的文章中复制整段:
比较应基于从每行输入中提取的一个或多个排序键(或者,如果未指定排序键,则整个行,直至终止,但不包括终止),并应使用当前区域设置的排序顺序执行。如果此排序序列没有所有字符的总顺序(请参阅XBD LC_COLLATE),则应使用POSIX语言环境的排序序列进一步逐字节比较所有排序相同的输入行
及
鼓励实现对相同排序的行执行建议的进一步逐字节比较,即使这可能会影响效率。如果当前区域设置的排序顺序没有所有字符的总顺序(如果实现提供了查询此顺序的方法),则仅通过执行额外的比较来减轻对效率的影响或者,如果与LC_COLLATE类别关联的区域名称中有“@”修饰符,则仅执行附加比较(因为没有“@”修饰符的区域名称应具有所有字符的总顺序-请参阅XBD LC_COLLATE)。请注意,如果实现提供了一个稳定的排序选项作为扩展(通常为-s),那么在指定此选项时不应执行额外的比较
问题:最后的比较是如何进行的 GNU coreutils的文档很快回答了这一问题: 一对行按如下方式进行比较:sort按照命令行上指定的顺序,根据相关的排序选项,对每对字段(请参见
--key
)进行比较,直到发现差异或没有字段。如果未指定键字段,sort将使用整行的默认键最后,作为最后一种手段,当所有键比较相等时,sort会比较整行,就好像没有指定除--reverse
(-r
)以外的任何排序选项一样。--stable
(-s
)选项禁用此最后的比较,以便所有字段比较相等的行保持其原始相对顺序。--unique
(-u
)选项也会禁用最后的比较
除非另有规定,否则所有比较都使用LC\u-COLLATE指定的字符排序序列
来源:
这意味着最终的解决方案将根据LC_COLLATE的排序顺序进行排序,即(主要)按字典顺序进行排序
另一方面,POSIX增加了一个更为严格的终极终极选择
如果此排序序列没有所有字符的总顺序(请参阅XBD LC_COLLATE),则应使用POSIX区域设置的排序序列对所有排序相同的输入行进行进一步的逐字节比较
来源:
我不确定这是否在GNU排序中实现,因为这不是一个要求。尽管如此,POSIX还是强烈推荐它(请参阅)
对于OP,这意味着什么?
对关键定义存在令人不安的误解。假设你做了类似的事情
$ sort --option -k1,3 file
通常认为,sort
将首先使用--选项对字段1进行排序,然后对字段2进行排序,最后对字段3进行排序。这是不正确的。它将使用定义为由字段1到3组成的子字符串的键。如果两行的排序相等,sort
将执行最后一个选项(见前面)
当您进行数字排序(使用-n
或-g
)时,sort
将尝试从键中提取一个数字(1234abc导致1234),并使用该数字进行排序
# Sort numerically with full line
# -------------------------------------------------------------------
$ echo -e "3a 11a\n3b 2b" | sort -n --debug
sort: using ?en_GB.UTF-8? sorting rules
3a 11a
_ # numeric on full line
______ # lexicographically on full line (last resort)
3b 2b
_ # numeric on full line
_____ # lexicographically on full line (last resort)
# -------------------------------------------------------------------
# Sort numerically with field 1 then field 2
# -------------------------------------------------------------------
$ echo -e "3a 11a\n3b 2b" | sort -n -k1,1 -k2,2 --debug
sort: using ?en_GB.UTF-8? sorting rules
3b 2b
_ # numeric on field 1
_ # numeric on field 2
_____ # lexicographically on full line (last resort)
3a 11a
_ # numeric on field 1
__ # numeric on field 2
______ # lexicographically on full line (last resort)
正如您注意到的,在这两种情况下,尽管第一个字段可以按字典顺序排序3a<3b
,但它被忽略,因为我们只从键中选择数字。我认为您可能在寻找不同的单词。可以预见吗?通过快速浏览,POSIX中没有与此相关的内容;事实上,POSIX甚至不包括-s
选项,其他tha
aa bb cc xxxxxxxx
--------- <<< rule1: according to the key
------------------ <<< rule2: lexicographical sort (last resort)
# Sort lexicographically with full line
# -------------------------------------------------------------------
$ echo -e "ab c d\nefg h i" | sort --debug
sort: using ?en_GB.UTF-8? sorting rules
ab c d
______
efg h i
_______
# -------------------------------------------------------------------
# Sort lexicographically with the substring formed by field 1 and 2
# -------------------------------------------------------------------
$ echo -e "ab c d\nefg h i" | sort -k1,2 --debug
sort: using ?en_GB.UTF-8? sorting rules
sort: leading blanks are significant in key 1; consider also specifying 'b'
ab c d
____
______
efg h i
_____
_______
# -------------------------------------------------------------------
# Sort lexicographically with field 1 followed by field 2
# -------------------------------------------------------------------
$ echo -e "ab c d\nefg h i" | sort -k1,1 -k2,2 --debug
sort: using ?en_GB.UTF-8? sorting rules
sort: leading blanks are significant in key 1; consider also specifying 'b'
sort: leading blanks are significant in key 2; consider also specifying 'b'
ab c d
__
__
______
efg h i
___
__
_______
# Sort numerically with full line
# -------------------------------------------------------------------
$ echo -e "3a 11a\n3b 2b" | sort -n --debug
sort: using ?en_GB.UTF-8? sorting rules
3a 11a
_ # numeric on full line
______ # lexicographically on full line (last resort)
3b 2b
_ # numeric on full line
_____ # lexicographically on full line (last resort)
# -------------------------------------------------------------------
# Sort numerically with field 1 then field 2
# -------------------------------------------------------------------
$ echo -e "3a 11a\n3b 2b" | sort -n -k1,1 -k2,2 --debug
sort: using ?en_GB.UTF-8? sorting rules
3b 2b
_ # numeric on field 1
_ # numeric on field 2
_____ # lexicographically on full line (last resort)
3a 11a
_ # numeric on field 1
__ # numeric on field 2
______ # lexicographically on full line (last resort)