某種奇怪的行為

某種奇怪的行為

我使用的是 Ubuntu 18.04 和預設的 coreutils。我注意到該命令的一個特殊行為sort,我不確定如何解釋。

考慮以下命令:

$ cat <<EOF | sort
0-
01-                                    
EOF
0-
01-

此輸出是有意義的,因為-ASCII 值小於預期值1,因此此輸出是預期的。

但是,如果我在最後多加一個字元:

$ cat <<EOF | sort
0-T
01-T
EOF
01-T
0-T

這個輸出對我來說沒有任何意義,因為我認為0-T應該放在第一位。為什麼會出現這種情況。我在這裡缺少什麼?我的期望是錯的嗎?

答案1

這取決於您所在區域的排序規則。

整理順序是針對每個區域設定的一組規則,允許對重音字母進行排序(例如,在西班牙語中將ñ出現在之後n但之前o)。

但事實並非如此,排序規則也規定了排序時要忽略哪些字元。對於語言環境“C”,會考慮所有字符,但對於“en_US”,例如,對於大多數其他語言環境,破折號(U002D) 會被忽略,因為它們繼承了iso14651_t1_common 的定義(在/usr/share/ 下) i18n/locales/ 在某些發行版中)。

因此,第一個檔案的排序不會造成問題,因為當您忽略破折號時,您最終會得到簡單的字母比較:

      -- ignore dashes -->      -- sort --> 
0-                          0               0
01-                         01              01 

當你添加“T”時,事情發生了變化,為什麼?因為現在,如果您忽略破折號,則必須比較“1”和“T”(第一個字元相同),並且“1”位於“T”之前:

      -- ignore dashes -->      -- sort --> 
0-T                          0T               01T
01-T                         01T              0T

因此,最好始終確保使用“C”的規則,並在排序時使用 LC_COLLATE=C。

在你的情況下:

$ cat <<EOF | LC_COLLATE=C sort
0-T
01-T
EOF

產量:

0-T
01-T

正如你所料。

答案2

是的,這可能看起來很煩人。 (預設語言環境為 en_US.UTF-8)

$ printf '%s\n' 1 1- 1-a 11- 11-a | sort
1
1-
11-
11-a
1-a

原因是 已-分配no weight給整理順序。

類似 a"應該做的事情:

printf '%s\n' 1 \"1\" 1- \"1-\" 1-a \"1-a\" 11- \"11-\" 11-a \"11-a\" | sort
"1"
"1-"
1
1-
"11-"
11-
"11-a"
11-a
"1-a"
1-a

正如您在上面看到的,所有 1 都排序在一起,11也全部。問題是它的1-a排序1a比其他任何東西都更像:

printf '%s\n' 1-a 1-b 1-c 1a 1b 1c| sort
1-a
1a
1-b
1b
1-c
1c

無論標點-";其他)是否應該包含在排序規則排序順序中是有爭議的。普遍的觀點是不應該(在非 ASCII 語言環境中)。

常見的大多數拉丁語言的文件是/usr/share/i18n/locales/iso14651_t1_common.在該文件中HYPHEN-MINUS(是​​的,用外行術語來說,我們稱之為破折號。Unicode U-002D)整理順序設定為:

<U002D> IGNORE;IGNORE;IGNORE;<U002D> % HYPHEN-MINUS

也就是說,忽略前三個等級的整理。

相關內容