簡體   English   中英

當未提供 --stable 選項時, sort -n 是否可以預測地處理關系? 如果有,怎么做?

[英]Does sort -n handle ties predictably when the --stable option is NOT provided? If it does, how?

在這里,兩行中3之后的空格似乎打破了數字排序並讓字母排序開始,因此11 < 2

$ echo -e '3 2\n3 11' | sort -n
3 11
3 2

man sort中,我讀到

 -s, --stable stabilize sort by disabling last-resort comparison

這意味着沒有-s會進行最后的比較(在關系之間,因為-s不會影響非關系)。

所以問題是:這個最后的比較是如何完成的? 如果有必要回答問題,歡迎參考源代碼。

這個答案 Unix從實驗中推斷出關系的排序是字典順序的。

標准/POSIX對此有什么說法嗎?

在這里,兩行中的 3 之后的空格似乎破壞了數字排序並讓字母排序開始

sort -n不是sort -n -k1,1 -k2,2 sort -n整行(不是fields ,)解釋為一個數字,例如atoi("3 11")給出3 然后對這些數字進行排序。 因為sort_them(atoi("3 11"), atoi("3 2"))是未排序的,因為兩者都是數字3 ,所以最后的比較排序開始了。

這個最后的比較是如何完成的?

這個想法是整個行都通過strcmp或類似(即strcoll )進行比較。 因為12之前,所以strcmp("3 11", "3 2")3 11排序為第一個。 不考慮任何選項,不考慮-n

如果有必要回答問題,歡迎參考源代碼。

實際上,GNU 排序中的xmemcoll0coreutils sort.c#L2653 中比較 (struct line const *a, struct line const *b)時考慮整理,並且當LC_COLLATE未設置時, memcmp作為后備。

我在 openbsd 排序中看到它在openbsd/sort/coll.c#L528 str_list_coll(struct bwstring *str1, struct sort_list_item **ss2)周圍,但也在list_coll_offset()中,如果所有鍵比較相等,則調用top_level_str_coll來排序整行。

標准/POSIX對此有什么說法嗎?

如果“this”指的是穩定排序和最后的比較,那么肯定。 讓我們從POSIX 排序重點中復制整個段落:

比較應基於從每行輸入中提取的一個或多個排序鍵(或者,如果未指定排序鍵,則為直到但不包括終止符的整行),並且應使用當前語言環境。 如果此整理序列沒有所有字符的總排序(請參閱 XBD LC_COLLATE),則應使用 POSIX 語言環境的整理序列逐字節進一步比較任何同等整理的輸入行。

鼓勵實現對同等整理的行執行推薦的進一步逐字節比較,即使這可能會影響效率。 如果當前語言環境的整理序列沒有所有字符的總排序(如果實現提供了一種查詢方法),或者僅在語言環境名稱的情況下執行附加比較,則可以通過僅執行附加比較來減輕對效率的影響與 LC_COLLATE 類別關聯的名稱中有一個“@”修飾符(因為沒有“@”修飾符的語言環境應該具有所有字符的總排序 - 請參閱 XBD LC_COLLATE)。 請注意,如果實現提供了一個穩定的排序選項作為擴展(通常是 -s),則在指定此選項時不應執行額外的比較。

問題:最后的比較是如何完成的?

這在 GNU coreutils 的文檔中很快得到了回答:

一對行的比較如下: sort 比較每一對字段(參見--key ),按照命令行上指定的順序,根據關聯的排序選項,直到發現差異或沒有字段。 如果未指定關鍵字段,則 sort 使用整行的默認鍵。 最后,作為最后的手段,當所有鍵比較相等時,sort 會比較整行,就好像沒有指定--reverse ( -r ) 以外的排序選項一樣 --stable ( -s ) 選項禁用此最后的比較,以便所有字段比較相等的行保留其原始相對順序。 --unique ( -u ) 選項也禁用最后的比較。

除非另有說明,否則所有比較都使用LC_COLLATE指定的字符整理順序

來源: 排序調用 GNU Coreutils

這意味着最終的手段將根據LC_COLLATE的排序順序進行排序,即按字典順序(大部分)。

另一方面,POSIX 添加了一個更嚴格的最終超最后手段選項。

如果此整理序列沒有所有字符的總排序(請參閱 XBD LC_COLLATE),則應使用 POSIX 語言環境的整理序列逐字節進一步比較任何同等整理的輸入行。

來源: 排序 POSIX 標准

我不確定這是否在 GNU 排序中實現,因為它不是必需的。 盡管如此,POSIX 強烈推薦它(參見理由最后一段

如果是 OP,這意味着什么?

對鍵定義存在令人不安的誤解。 假設你做類似的事情

$ sort --option -k1,3 file

通常理解sort將首先使用--option對字段 1 進行排序,然后是 2,最后是 3。 這是不正確的。 它將使用定義為 substring 的密鑰,該密鑰由字段 1 到 3 組成。如果兩行相等, sort將執行最后的選項(見前面)

aa  bb cc xxxxxxxx
---------           <<< rule1: according to the key
------------------  <<< rule2: lexicographical sort (last resort)

使用 GNU 排序,您可以看到哪個 substring 用於排序。 這是通過--debug選項完成的。 在這里,您可以看到 3 個簡單案例之間的區別:

# 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
___
   __
_______

當您進行數字排序(使用-n-g )時, sort將嘗試從key中提取一個數字(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 ,它也會被忽略,因為我們只從鍵中選擇數字。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM