無論是工作中使用還是應付各種面試,linux sort 都是必須要掌握的 linux 基本命令之一。尤其是 linux sort -k 命令,經常會被搞暈,索性好好研究一下 sort 命令
sort 對文件內容進行排序
語法:
sort [-bcdfimMnr][-o<輸出文件>][-t<分隔字符>][+<起始欄位>-<結束欄位>][--help][--verison][文件]
選項:
-b:忽略每行前面開始的空格字符,空格數量不固定時,該選項幾乎是必須要使用的("-n"選項隱含該選項,測試發現都隱含) -c:檢查文件是否已經按照順序排序,如未排序,會提示從哪一行開始亂序 -C:類似於"-c",只不過不輸出任何診斷信息。可以通過退出狀態碼1判斷出文件未排序 -d:只處理英文字母、數字及空格,忽略其他的字符 -f:將小寫字母視為大寫字母 -h:使用易讀性數字(例如:2K、1G) -i:除了040至176之間的ASCII字符外(八進制0-177),忽略其他的字符(忽略無法打印的字符如退格/換頁鍵/回車) -k:以哪個區間 (field) 來進行排序 -m:將幾個排序好的文件進行合並,只是單純合並,不做排序 -M:將前面3個字母依照月份的縮寫進行排序 -n:依照數值的大小排序 -o<輸出文件>:將排序后的結果存入指定的文件 -r:降序 -u:忽略相同行 -t<分隔字符>:指定分隔符,默認的分隔符為空白字符和非空白字符之間的空字符
參數就不一一介紹了,直接上例子,首先先看下原始的排序數據 cat sort.log
a mac 2000 500 2K
d winxp 4000 300 3G
e bsd 1000 600 4M
b linux 1000 200 5K
f SUSE 4000 300 6M
g winxp 500 300 3G
c win7 2000 100 7G
c Debian 600 200 8K
1、打印從哪列開始是亂序 sort -c sort.log; echo $?
sort: sort.log:4: disorder: b linux 1000 200 5K 1
sort -C sort.log; echo $?
1
其中,返回結果 1,表示文件不是已經排序好的文件 2、默認排序( 整行進行ASCII字符升序) sort sort.log
a mac 2000 500 2K
b linux 1000 200 5K
c Debian 600 200 8K
c win7 2000 100 7G
d winxp 4000 300 3G
e bsd 1000 600 4M
f SUSE 4000 300 6M
g winxp 500 300 3G
3、高能來了,讓人迷糊的 k 語法,首先看下 k 的語法格式
[ FStart [ .CStart ] ] [ Modifier ] [ , [ FEnd [ .CEnd ] ][ Modifier ] ]
這個語法格式可以被其中的逗號(”,”)分為兩大部分,Start部分和End部分 Start和End部分都由三部分組成,其中的Modifier部分就是類似n和r的選項部分,可省略 FStart、Fend,表示使用的域,而CStart則表示在FStart域中從第幾個字符開始算"排序首字符",同理,CEnd表示結尾的第幾個字符是排序末尾字符,.CStart、.CEnd是可以省略的,分別表示從本域的開頭部分開始、到本域的域尾結束,CEnd設定為0,也是表示結尾到域尾。口說無憑,上幾個例子吧
3.1 對第三列進行排序,如果不加n,按照 ASCII字符排序 sort -t $'\t' -k 3 sort.log
b linux 1000 200 5K
e bsd 1000 600 4M
c win7 2000 100 7G
a mac 2000 500 2K
d winxp 4000 300 3G
f SUSE 4000 300 6M
g winxp 500 300 3G
c Debian 600 200 8K
3.2 加n后,按照數值排序 sort -t $'\t' -k 3n sort.log
g winxp 500 300 3G
c Debian 600 200 8K
b linux 1000 200 5K
e bsd 1000 600 4M
a mac 2000 500 2K
c win7 2000 100 7G
d winxp 4000 300 3G
f SUSE 4000 300 6M
3.3 不指定 FEnd 時,多個 -k 從前往后排序可以,從后往前不行 從后往前,多個 -k,數據符合預期 sort -t $'\t' -k 3n -k 1 sort.log
g winxp 500 300 3G
c Debian 600 200 8K
b linux 1000 200 5K
e bsd 1000 600 4M
a mac 2000 500 2K
c win7 2000 100 7G
d winxp 4000 300 3G
f SUSE 4000 300 6M
從后往前,多個 -k ,第三列相同時,按照第一列降序排列,數據符合預期 sort -t $'\t' -k 3n -k 1r sort.log
g winxp 500 300 3G
c Debian 600 200 8K
e bsd 1000 600 4M
b linux 1000 200 5K
c win7 2000 100 7G
a mac 2000 500 2K
f SUSE 4000 300 6M
d winxp 4000 300 3G
更換成從前往后 sort -t $'\t' -k 1 -k 3n sort.log
a mac 2000 500 2K
b linux 1000 200 5K
c Debian 600 200 8K
c win7 2000 100 7G
d winxp 4000 300 3G
e bsd 1000 600 4M
f SUSE 4000 300 6M
g winxp 500 300 3G
sort -t $'\t' -k 1 -k 3nr sort.log
a mac 2000 500 2K
b linux 1000 200 5K
c Debian 600 200 8K
c win7 2000 100 7G
d winxp 4000 300 3G
e bsd 1000 600 4M
f SUSE 4000 300 6M
g winxp 500 300 3G
通過 sort -t $'\t' -k 1 -k 3n sort.log
和 sort -t $'\t' -k 1 -k 3nr sort.log
返回的結果發現,在第一列相等時,無論其三列是正序排列,還是逆序排列,結果都一樣,說明后邊的 -k 未生效 當指定 FEend 后 sort -t $'\t' -k 1,1 -k 3nr sort.log
a mac 2000 500 2K
b linux 1000 200 5K
c win7 2000 100 7G
c Debian 600 200 8K
d winxp 4000 300 3G
e bsd 1000 600 4M
f SUSE 4000 300 6M
g winxp 500 300 3G
3.4 作用域 緊跟在字段后的選項(如"-k3n"的"n"和"-k2nr"的"n","r")稱為私有選項,使用短橫線寫在字段外的選項(如"-n"、"-r")為全局選項。當沒有為字段分配私有選項時,該排序字段將繼承全局選項,所有選項包括但不限於"bfnrhM" 除了"b"選項外,其余選項無論是指定在FStart還是FEnd中都是等價的,對於"b"選項,指定在FStart則作用於FStart,指定在FEnd則作用於FEnd sort -t $'\t' -k1r,2 sort.log
,可以看出一、二列都是倒敘排列
g winxp 500 300 3G
f SUSE 4000 300 6M
e bsd 1000 600 4M
d winxp 4000 300 3G
c win7 2000 100 7G
c Debian 600 200 8K
b linux 1000 200 5K
a mac 2000 500 2K
3.5 注意 指定n選項按數值排序時, 由於"n"選項只能識別數字和負號"-",當排序時遇到無法識別字符時,將導致該key的排序立即結束,n選項絕對不會跨域進行比較 默認情況下,sort會進行一次"最后的排序",按照默認規則對整行進行一次排序,這次排序稱為"最后的排序"
sort -t $'\t' -k3n sort.log
,在第三列相等時,整行會按照 ASCII 進行最后的升序排列
g winxp 500 300 3G
c Debian 600 200 8K
b linux 1000 200 5K
e bsd 1000 600 4M
a mac 2000 500 2K
c win7 2000 100 7G
d winxp 4000 300 3G
f SUSE 4000 300 6M
sort -t $'\t' -k3,4n -s sort.log
,加了 -s 后,不會進行最后的排序(1000相同時,e在b的前邊了),而是保留原排序
g winxp 500 300 3G
c Debian 600 200 8K
e bsd 1000 600 4M
b linux 1000 200 5K
a mac 2000 500 2K
c win7 2000 100 7G
d winxp 4000 300 3G
f SUSE 4000 300 6M
3.6 按照某個域中的第n個字符進行排序 sort -t $'\t' -k2.3,2.3 sort.log
,按第二列第三個字符進行排序
c Debian 600 200 8K
a mac 2000 500 2K
e bsd 1000 600 4M
b linux 1000 200 5K
c win7 2000 100 7G
d winxp 4000 300 3G
g winxp 500 300 3G
f SUSE 4000 300 6M
4、 -h 使用易讀性數字(例如:2K、1G) sort -t $'\t' -k5h sort.log
a mac 2000 500 2K
b linux 1000 200 5K
c Debian 600 200 8K
e bsd 1000 600 4M
f SUSE 4000 300 6M
d winxp 4000 300 3G
g winxp 500 300 3G
c win7 2000 100 7G
- sort –u 和 sort | uniq 區別 如果sort 指定 -k 選項,是不等價的, uniq默認是對整行進行去重
sort -t $'\t' -k2,2 -u sort.log
e bsd 1000 600 4M
c Debian 600 200 8K
b linux 1000 200 5K
a mac 2000 500 2K
f SUSE 4000 300 6M
c win7 2000 100 7G
d winxp 4000 300 3G
sort -t $'\t' -k2,2 sort.log|uniq
e bsd 1000 600 4M
c Debian 600 200 8K
b linux 1000 200 5K
a mac 2000 500 2K
f SUSE 4000 300 6M
c win7 2000 100 7G
d winxp 4000 300 3G
g winxp 500 300 3G
sort -t $'\t' -k2,2 -u sort.log
會對第二列進行去重,而 sort -t $'\t' -k2,2 sort.log|uniq
會對整行進行去重(當然uniq也可以按照第二列進行去重)
sort整理完了,歡迎大牛指教