鍍金池/ 教程/ Linux/ shell 學(xué)習(xí)第十八天----文本排序
shell 學(xué)習(xí)四十一天----列出文件 ls 和 od 命令
shell 學(xué)習(xí)小結(jié)
shell 學(xué)習(xí)第二十八天----case 語句
shell 學(xué)習(xí)四十四天----尋找文件
shell 學(xué)習(xí)三十五天----波浪號展開與通配符
shell 學(xué)習(xí)三十八天----執(zhí)行順序和 eval
shell 學(xué)習(xí)四十八天----文件校驗和匹配
shell 學(xué)習(xí)四十天----awk 的驚人表現(xiàn)
shell 學(xué)習(xí)第十一天----sed 正則的精確控制
shell 學(xué)習(xí)第十七天----awk 命令
shell 學(xué)習(xí)三十九天----內(nèi)建命令
shell 學(xué)習(xí)四十五天----xargs
shell 學(xué)習(xí)三十七天----引用
shell 學(xué)習(xí)第十六天----join 練習(xí)
shell 學(xué)習(xí)第二十四天----提取開頭或結(jié)尾數(shù)行
shell 學(xué)習(xí)第九天----分組
shell 學(xué)習(xí)第五天----基本的 I/O 重定向
shell 學(xué)習(xí)第十五天----使用 cut 選定字段
shell 學(xué)習(xí)四十六天----文件系統(tǒng)的空間信息 df 和 du 命令
shell 學(xué)習(xí)第八天----擴展正則表達式 (ERE)
shell 學(xué)習(xí)第十九天----文本塊排序
shell 學(xué)習(xí)第二十一天----重新格式化段落
shell 學(xué)習(xí)三十六天----命令替換
shell 學(xué)習(xí)第二十天----sort 的其他內(nèi)容以及 uniq 命令
shell 學(xué)習(xí)四十二天----使用 touch 更新文件時間
shell 學(xué)習(xí)五十一天----top 命令查看進程列表
shell 學(xué)習(xí)第一天
shell 學(xué)習(xí)五十四天----進程系統(tǒng)調(diào)用的追蹤 strace
shell 學(xué)習(xí)五十天----查看進程 ps 命令
shell 學(xué)習(xí)第二十七天----退出狀態(tài)和 if 語句
shell 學(xué)習(xí)第二十三天----打印
shell 學(xué)習(xí)三十三天----關(guān)于重定向
shell 學(xué)習(xí)四十九天----進程建立
shell 學(xué)習(xí)第三十天----break,continue,shift,getopts
shell 學(xué)習(xí)五十五天----進程記賬
shell 學(xué)習(xí)總結(jié)一
shell 學(xué)習(xí)第二十六天----變量與算數(shù)
shell 學(xué)習(xí)第二十二天----計算行數(shù), 字數(shù)以及字符數(shù)
shell 學(xué)習(xí)五十八天----/proc 文件系統(tǒng)
shell 學(xué)習(xí)第二十五天----神器的管道符
shell 學(xué)習(xí)第三十二天----read 讀取一行
sheel 學(xué)習(xí)第三天
shell 學(xué)習(xí)----小結(jié)
shell 學(xué)習(xí)第十八天----文本排序
shell 學(xué)習(xí)第三十一天----函數(shù)問題
shell 學(xué)習(xí)第十天----sed 查找與替換
shell 學(xué)習(xí)四十三天----臨時性文件的建立與使用
shell 學(xué)習(xí)四十七天----文件比較 cmp,diff,patch
shell 學(xué)習(xí)三十四天----printf 詳解
shell 學(xué)習(xí)五十七天 ----linux 任務(wù)管理,針對上一講的總結(jié)和擴展
shell 學(xué)習(xí)第六天----小結(jié)
shell 學(xué)習(xí)第十三天----sed 案例分析
shell 學(xué)習(xí)第七天----基礎(chǔ)正則表達式 (BRE)
shell 學(xué)習(xí)第十二天----行與字符串
shell 學(xué)習(xí)小結(jié)四
shell 學(xué)習(xí)第二十九天----循環(huán)
shell 學(xué)習(xí)五十二天----刪除進程 kill 命令
shell 學(xué)習(xí)五十六天----延遲進程調(diào)度
shell 學(xué)習(xí)第四天----華麗的 printf 輸出
shell 學(xué)習(xí)第十五天----join 連接字段
shell 學(xué)習(xí)完結(jié)篇----希望你能看到
shell 學(xué)習(xí)第二天
shell 學(xué)習(xí)五十三天----捕獲信號 trap

shell 學(xué)習(xí)第十八天----文本排序

排序文本

行的排序,使用的命令 sort,該命令的語法是: sort [option] [files...].sort 將文件 / 文本的每一行作為一個單位,相互比較,比較原則是從首字符向后,依次按 ASCII 碼值進行比較,最后將他們按升序輸出。

入門案例

有一個文件 temp.txt,內(nèi)容為:

aaa:10:1.1ccc:30:3.3ddd:40:4.4bbb:20:2.2eee:50:5.5eee:50:5.5

使用 sort temp.txt 輸出結(jié)果為:

aaa:10:1.1bbb:20:2.2ccc:30:3.3ddd:40:4.4eee:50:5.5eee:50:5.5

再來看 sort 的各個選項的使用:

  • -b:忽略每行前面開始處的空格字符;
  • -c:檢查文件是否已經(jīng)按照順序排序,排序過為真;
  • -d:排序時,處理英文字母、數(shù)字和空格字符,以字典順序排序。忽略其他所有字符;
  • -f:排序時,將小寫字母視為大寫字母;
  • -i:排序時,處理 040~176 之間的 ASCII 字符,忽略其他所有字符;
  • -m:將幾個排序好的文件進行合并;
  • -M:將前面 3 個字母按月份的縮寫進行排序;
  • -n:按照數(shù)值大小進行排序;
  • -o outfile.txt:將排序后的結(jié)果存入 outfile.txt;
  • -r:以相反的順序進行排序;
  • -k:指定需要排序的列數(shù)(欄數(shù));
  • -t 分隔符:指定排序時所用到的欄位分隔符;
  • + 起始欄位 - 結(jié)束欄位:以指定的欄位來排序,范圍從起始欄位到結(jié)束欄位的前一欄位。(古老的用法)

案例:

使用 -u 選項的輸出,還是針對文件 temp.txt

aaa:10:1.1
bbb:20:2.2
ccc:30:3.3
ddd:40:4.4
eee:50:5.5

例如:

有一個文件 sort.txt,內(nèi)容為:

AA:BB:CC
   aaa:30:1.6
   ccc:50:3.3
   ddd:20:4.2
   bbb:10:2.5
   eee:40:5.4
   eee:60:5.1

使用 sort -nk 2 -t: sort.txt 排序后的結(jié)果為:

AA:BB:CC
bbb:10:2.5
ddd:20:4.2
aaa:30:1.6
eee:40:5.4
ccc:50:3.3
eee:60:5.1

上述命令的意思是說,將第二列按照數(shù)字從小到大排列

使用 sort -nrk 3 -t: sort.txt,該命令的意思是說,將第三列數(shù)字從大到小排列,所以輸出的結(jié)果為:

eee:40:5.4
eee:60:5.1
ddd:20:4.2
ccc:50:3.3
bbb:10:2.5
aaa:30:1.6
AA:BB:CC

備注: -n 是按照數(shù)字大小排序,-r 是以相反順序,-k 是指定需要排序的欄位,-t 指定欄位分隔符為冒號。

問題: 有一個文件,內(nèi)容為:

banana:30:5.5
apple:10:2.5
pear:90:2.3
orange:20:3.4

第一列表示水果名稱,第二列表示水果數(shù)量,第三列表式水果價格。我想按照水果的數(shù)量進行排序,怎么辦?

  • sort -nk 2 -t : fruit.txt(從小到大排序)
  • sort -nrk 2 -t : fruit.txt(從大到小排序,注意選項的位置)

如果我想給 /etc/passwd 按照第三行排序,應(yīng)該是這樣:

  • sort -t':' -k 3 /etc/passwd,但是細心的你一定會發(fā)現(xiàn)其中的問題,貌似不對啊? 不應(yīng)該啊? 那是因為 -k 選項默認是按照字典數(shù)排列,如果想按照數(shù)字排列需要指定 sort -t':' -k 3n /etc/passwd,也就是需要加上 -n 選項。

如果想逆序排列呢?

  • sort -t':' -k 3nr /etc/passwd

如果要對 /etc/passwd 文件中第六列的第二個字符到第四個字符正序排列,再基于第一列進行反向排序。

  • sort -t':' -k 6.2,6.4 -k 1r /etc/passwd 引入一個關(guān)于 -k 選項的新知識。

-k 選項的語法格式

FStart.CStart Modifie,FEnd.CEnd Modifier-------Start--------,-------End-------- FStart.CStart 選項,F(xiàn)End.CEnd 選項

這個語法格式可以被其中的逗號(“,”)分為兩大部分,Start 部分和 End 部分。Start 部分也由三部分組成,其中的 Modifier 部分就是我們之前說過的類似 n 和 r 的選項部分。我們重點說說 Start 部分的 FStart 和 C.Start。C.Start 也是可以省略的,省略的話就表示從本域的開頭部分開始。FStart.CStart,其中 FStart 就是表示使用的域,而 CStart 則表示在 FStart 域中從第幾個字符開始算 “排序首字符”。同理,在 End 部分中,你可以設(shè)定 FEnd.CEnd,如果你省略.CEnd,則表示結(jié)尾到 “域尾”,即本域的最后一個字符?;蛘?,如果你將 CEnd 設(shè)定為 0(零),也是表示結(jié)尾到 “域尾”。

那么很顯然 -k 6.2,6.4 的意思很明確,第六個字段的第二個字符到第六個字段的第四個字符. 按照正序排列。

案例

查看 /etc/passwd 有多少個 shell: 對 /etc/passwd 的第七個域進行排序,然后去掉重復(fù)的行:

cat /etc/passwd | sort -t':' -k 7 -u

sort 的行為模式: 它會讀取指定的文件,如果文件未給出,則讀取標準輸入,再將排序好的數(shù)據(jù)寫至標準輸出。

總結(jié):

  • 如果按照行排序,使用 -k 6; 按照字段排序,使用 -k 6.2 6.4 這樣的書寫格式。字段以及字段里的字符是有 1 開始。如果進指定一個字段編號,則排序鍵值會自該字段的起始處開始,一直繼續(xù)到記錄的結(jié)尾 (而非字段的結(jié)尾)。
  • 使用逗號 (或者空格) 隔開的字段,是由逗號 (或者空格) 左邊開始,逗號 (或者空格) 右邊結(jié)束。例如:-k 6.2,6.4 表示從第六個字段的第二個字符到第六個字段的第四個字符。
  • 當(dāng)出現(xiàn)多個 -k 選項的時候,會先從第一個鍵值字段開始排序,找出匹配該鍵值的記錄后,再進行第二個鍵值字段的排序,以此列推。