
我正在嘗試使用對一些數據進行排序sort
。我注意到它是按數字而不是數字排序,所以我添加了標誌-n
。不過,它似乎只是對第一個欄位進行數字排序。按字段分解它是一個問題,因為這些行具有不同數量的字段(坦率地說,我無法理解它的行為)。這是我正在使用的一些足夠接近的範例數據:
echo -e "b b 1\n23 44\nb 3\na 7\nb b 2\na 1\nb a 10\nb b 10\nb 1\nb a 1\n18 2\nb 10\n18 15\nb a 2\n23 9\nb 2" | sort -n
Input Want Expect? sort -n -n -k1,1 -k2,2 -k3,3 -k4,4…
b b 1 8 2 a 1 23 44 a 1 b a 1
23 44 8 15 a 7 23 9 a 7 b a 10
b 3 23 9 b a 1 8 15 b 1 b a 2
a 7 23 44 b a 2 8 2 b 10 b b 1
b b 2 a 1 b a 10 a 1 b 2 b b 10
a 1 a 7 b b 1 a 7 b 3 b b 2
b a 10 b 1 b b 2 b 1 b a 1 a 1
b b 10 b 2 b b 10 b 10 b a 10 b 1
b 1 b 3 b 1 b 2 b a 2 b 2
b a 1 b 10 b 2 b 3 b b 1 b 3
8 2 b a 1 b 3 b a 1 b b 10 a 7
b 10 b a 2 b 10 b a 10 b b 2 b 10
8 15 b a 10 8 2 b a 2 8 15 8 2
b a 2 b b 1 8 15 b b 1 8 2 8 15
23 9 b b 2 23 9 b b 10 23 44 23 9
b 2 b b 10 23 44 b b 2 23 9 23 44
理想情況下,我希望它能夠在具有 GNU coreutils sort 5.93 的機器上運行。我想用簡單的unix工具來處理它;我不想把問題交給 perl 等。sort --numeric-sort --all-fields --actually-work
答案1
我認為你的問題是你不明白sort
在做什麼。基本排序基於 ASCII 字元值,其中數字在大寫字母之前,數字在小寫字母之前:'1' == 49、'A' == 65、'a' = 97 sort
。 23 ' 排序在 '8 ' 之前,而 '8 ' 位於 'b b' 之前:'2' 的 ASCII 值為 50,'8' 的 ASCII 值為 56,'b' 為 98。
按數字排序 ( sort -n
) 時,非數字條目按常規方法排序,但與數字相比時解釋為 0,例如 23 或 8;但由於該值被視為數字而不是字元值,因此“8”位於“23”之前。因此,字母條目將排序在數字條目之前。
最好的方法是標準化數據,使每列具有相同類型的值:要么全部是數字,要么全部是字母數字,並適當排序。
在最後一列(按欄位排序)中,它將首先對具有更多欄位的條目進行排序,因為您明確指定了 4 個(或更多)欄位。所以 (1,2,3) 將在 (1,2) 之前。如果沒有該-k
選項,排序會將行作為一個整體考慮在內。
您可以閱讀有關的更多信息資訊 coreutils 排序頁。
答案2
echo -e "b b 1\n23 44\nb 3\na 7\nb b 2\na 1\nb a 10\nb b 10\nb 1\nb a 1\n18 2\nb 10\n18 15\nb a 2\n23 9\nb 2" \
| sed -r 's/[a-z]/9999&/g' | sort -n -k1 -k2 -k3 | sed 's/9999//g'
18 2
18 15
23 9
23 44
a 1
b 1
b 2
b 3
a 7
b 10
b a 1
b b 1
b a 2
b b 2
b a 10
b b 10
這就是你想要的嗎?如果是數字,則按數字排序,並將數字放在其他字元之前?
我在每個字串前面加上一個大數字作為前綴,以便透過排序將字串放在最後,並在最後刪除大數字(9999)。
答案3
經過幾年的發展,sort -V
onsort 8.26
產生了所需的輸出:
$ echo -e "b b 1\n23 44\nb 3\na 7\nb b 2\na 1\nb a 10\nb b 10\nb 1\nb a 1\n8 2\nb 10\n8 15\nb a 2\n23 9\nb 2" \
| sort -V
8 2
8 15
23 9
23 44
a 1
a 7
b 1
b 2
b 3
b 10
b a 1
b a 2
b a 10
b b 1
b b 2
b b 10