UNIX 文字工具: 排序

sort 是將文字檔以列為單位、按照字典排法做排序工作的指令。 所謂以列為單位,就是只要移動順序,必定是整列一起移動。 排序的根據,並非按照英文字母的順序,而是按照字碼的順序來排序, 通常是小號碼排在前面,大號碼在後面。 所以數目字必定排在前面,大寫英文字母隨之,小寫英文字母再隨之, 這其中還有一些符號,請參照 ASCII 表。 所謂字典排法,就是先比較每一列的第一格字碼。 第一格字碼比較小的,一定排在第一格字碼比較大的前面。 第一格字碼相同的必定排在一起, 然後再來比第二格字碼。 第一格必定非空,因為即使空列也有一個折列指令。 但第二格以後可能就是空的,如果是空的,就算最小。

不妨先實驗幾個例子:

sort indian.txt
所得的結果應該是
eight little
five little
four little
nine little Indians
one little
seven little
six little Indians
ten little Indian boys
three little Indians
two little
或者
head -20 forty.txt | tail -10 | sort
所得的結果應該是
eight little
five little
four little
nine little Indians
one little
seven little
six little Indians
ten little Indian girls
three little Indians
two little

因為 sort 接受 stdin 的輸入,讀者可以直接在文字介面中練習,如下:

sort
游標停在下一列的第一格,輸入
call
chase
China
Chinese
Canada  
Chile
然後按 Ctrl+D 結束輸入,sort 就執行排序,結果寫在 stdout,應該是
Canada
Chile
China
Chinese
call
chase
因為 c 的 ASCII 碼比 C 的大,所以 call 和 chase 必定排在後面。 第一格同樣是 C 的列,因為 a 的 ASCII 碼比比 h 的小,所以 Canada 在最前面。 第二格同樣是 h 的列,第三格也同樣是 i,這些字排在一起。 因為 l 的 ASCII 碼比比 n 的小,所以 Chile 在最前面。 依此類推。

如果要 sort 不分大小寫,可以用參數 -f (fold cases),例如前面的實驗, 如果用 sort -f 來做,結果就應該是

call
Canada  
chase
Chile
China
Chinese
可見 sort 將 C 和 c 視為一樣的字母。

要做數的排列時,最好使用 -n (numerical) 參數。否則 12 可能排在 2 的前面。 這是因為 sort 並不認為 12 是個整數,它認為 12 是數目字 1 跟著數目字 2。 而數目字 1 的 ASCII 號碼比 2 的小,所以 12 就排到 2 的前面了。 可以在終端機上做實驗。先下指令 sort,然後用鍵盤輸入

13
17
7
19
11
3
23
5
[Ctrl+D]
所得的結果是
11
13
17
19
23
3
5
7
但是如果用 sort -n 答案就對了。

如果想要 sort 倒過來排序,亦即從大到小,可以用參數 -r。 跟其他 UNIX 指令一樣,參數大多可以合併使用,例如 sort -nr 就是說要將數從大到小排序。例如

cat -n indian.txt | sort -nr
就會將 indian.txt 的列順序反置。讀者可以練習用 sed 將列號刪除。

如果在課堂中由教師帶領練習,請在這裡巡堂檢查學生是否跟上了, 要求學生以 indian.txt 為例,當場做底下的習題。

sort 也可以一次給它許多檔案。 這個意義是將所有輸入的檔案合在一起 (merge) 排序的意思。 所以若 FA 有 17 列,FB 有 20 列,則

sort FA FB
就會將兩個檔案,總共 37 列,放在一起排序。

排序的結果寫在 stdout,所以可以導入檔案。 但是導入之檔案不可以是原來排序的檔案。 例如

sort indian.txt >! indian.txt
是不可以的,這造成許多麻煩。好在 sort 給我們一個選擇,可以說
sort -o indian.txt indian.txt
這樣就會把 indian.txt 排序,然後將結果覆蓋 indian.txt 檔案。 如果要將許多個檔案合在一起排序,則 -o 指定的輸出檔案, 可以是許多輸入檔案之中的一個。 一旦指定了檔案名,stdin 就沒用了。

習題

  1. 如何將一個純文字檔案的列順序反置,例如將
    one little
    two little
    three little Indians
    
    變成
    three little Indians
    two little
    one little
    

[ 前一節 ]‧[ 後一節 ]‧[ 回目錄 ]



注意:此處所有文件均為原著,個別的版權宣告日後會一一公布, 整體版面設計亦尚未完成。但仍請勿抄襲文字與圖片,以免觸犯著作權法。

Created: Nov 19, 2000
Last Revised: Nov 19, 2000
© Copyright 2000 Wei-Chang Shann 單維彰

shann@math.ncu.edu.tw