組合的力量
本單元主要參考 GNU textutils 軟體的手冊寫成, 特別推薦 Opening the software toolbox "Toolbox Introduction" 與 "Putting the tools together" 兩節的觀念。
學會 以組合的方式操作電腦, 才能夠以有限的記憶力解決成千上萬沒有見過的問題. 「技術人員觀點」一文當中的 「組合的力量」 一段, 以類比的方式說明這種思考模式的重要性; 而這篇技術性的講義則提供具體的操作實例。
- 請複習 輸入輸出重新導向 與 命令結果代換 兩大重要觀念, 以及 cat、 head、 tail、 wc、 grep、 sed 等命令。
- sort 命令: 以列為單位, 對輸入資料排序.
- -n 把資料視為數字排序
- -r 倒過來排
- +3 -5 根據第 3,4 兩欄排序
- -t ':' 把 ':' 視為欄位的分隔符號
- cut 命令: 只保留某些欄位印出 (和 grep 正好 "垂直")
- -c 11-20,31-40 印出每列的第 11 到第 20 個字元, 以及第 31 到第 40 個字元.
- -f 2-4,5-8 印出每列的第 2,3,4,5,6,7,8 等欄位 (內定以 tab 鍵分隔欄位)
- -d ':' 把 : 當做欄位的分隔字元
- uniq 命令: 假設輸入資料已經過排序, uniq
可以用來把重複出現的列刪除到只出現一次.
- -c 額外印出每列重複了多少次
- -u 只列出沒有重複的列
- -d 只列出有重複的列
- tr 命令: 把輸入資料裡面的每個 ... 字元都改成 ... 範例:
- 把 DOS/Windows 傳上來的檔案後面的 ^M 去掉
(把結果印在螢幕上)
tr -d '\r' < config.sys - 把所有英文字母變成小寫 (把結果印在螢幕上)
tr 'A-Z' 'a-z' < config.sys
- 把 DOS/Windows 傳上來的檔案後面的 ^M 去掉
(把結果印在螢幕上)
- expand 命令: 把所有的 tab 鍵都換成適當個數的空白鍵
- paste 命令: 把檔案並排印出 (和 cat 正好 "垂直")
- join 命令: 類似 paste, 但是並排時未必把來自不同檔案的同一列合成一列, 而是依據特定欄位內相同的值來決定那幾列要合併. 輸入資料必須事先排序過. 把 join 命令與其他命令組合運用, 可以用純文字檔案來實作簡單的資料庫系統.
更多範例:
- 看看目前目錄下那些檔案占用的空間最多
ls -l | sort -n +4 - 看看整個系統內那些程序吃記憶體吃得最兇
ps aux | sort -n +3 - 看看那些使用者的 "GECOS" 欄位有資訊 (見 man 5 passwd)
grep ',' /etc/passwd | cut -d ':' -f 5 - 看看自己家裡面所有最上層的子目錄各用了多少空間
du -s $(ls -l ~ | grep '^d' | cut -c 55-) - 把使用者 ckhung 所有正在執行的程序全部中斷掉
kill $(ps aux | grep '^ckhung' | cut -c 9-16) - 看看有那些使用者有程序在執行 (無論有無控制臺)
ps aux | cut -c 1-8 | sort | uniq
上例中如果用 uniq -c 則列出每個人正在執行多少個程序 - (以下只是一個技術範例; 但實際上不論從禮貌/隱私/安全
的角度來看, 這麼做都不太好, 請不要濫用!)
假設過去幾個月以來我所收到的所有信件都放在 mbox 檔當中;
而我有一封公開信放在 announce 檔案內. 如何把公開信寄給
"過去幾個月以來曾經寄信給我的人"?
有一些信的寄件人不需要收到我的公開信, 像是系統 (退信), 我自己,
所有的英國筆友... 等等人. 我把他們的 e-mail 樣版都放在 exclude
這個檔案內, 內容像這樣:
MAILER-DAEMON ckhung \.uk$
深呼吸...請看:mail $(perl -ne 'print "$1\n" if /^From:.*<(.*@.*)>/' mbox | sort | uniq | grep -v -f exclude a) < announce
(通通打在同一列, 不要換列!) - 想找找看 time_t 這個型別究竟是在那個系統標頭檔中定義的:
grep time_t $(find /usr/include/ -type f) | grep typedef
- 製作 orig 這個目錄下所有檔案的 md5 checksum:
md5sum $(find orig -type f) > orig.md5
用途: 想比較兩個很相似的目錄, 是否它們底下所有相對應的檔案內容都相同? 可以對這兩個目錄下上述的命令, 再用 diff 比較結果 (orig.md5 與 new.md5). 如果結果相同, 那麼這兩個目錄的內容完全相同的機率幾乎是 1. - 看看目前目錄 (及子目錄孫目錄 ...) 下有那些檔案是 perl 程式,
並依大小排列出來:
file $(find . -type f) | grep 'perl commands text' | sed 's/:.*$//' | xargs wc | sort -n
- 把自己家裡所有已公開的網頁包成一個壓縮檔:
tar czf mypages.tgz $(find public_html/ -type f -perm +044)
- 在 abc 目錄下 (含子目錄, 孫目錄, ...) 尋找所有內含 pqr
字串的檔案, 並把這些 pqr 都改成 xyz:
grep -l pqr $(find abc -type f) > ttt; perl -i -pe 's/pqr/xyz' $(cat ttt)
- 把目前目錄下所有最近三天內修改過的檔案按照大小排出來:
ls -l $(find . -type f -mtime -3) | sort -n +4
- 因應 CLE 首頁網址由 http://cle.linux.org.tw/CLE/ 改為 http://cle.linux.org.tw/ 想一次將自己的 ~/public_html/ 目錄下所有提及 CLE 舊網址的地方一口氣更新: 先找出所有提及 CLE 舊網址的檔案: grep -l 'http://cle.linux.org.tw/CLE' $(find . -type f) > ~/f 再用 regexp 一次更新: perl -pi.bak -e 's#http://cle.linux.org.tw/CLE/?#http://cle.linux.org.tw/#g' $(cat ~/f)
- 把目前目錄底下所有 dos 格式文字檔, 轉成 unix 格式:
file $(find . -type ) | grep -i text | sed 's/: .*//' > /tmp/listing; perl -i -pe 's/\015//' $(cat /tmp/listing)
- 本來有很多 .mp3 檔分別放在很多子目錄底下。 但是有些較舊的 mp3
player 處理目錄會出問題, 所以將它們全部移到目前這一層目錄。
現在想將這些已經清空的目錄刪除掉:
rmdir $(ls | grep -v '\.mp3$' )
env | grep -i tw
出現許多與 locale 相關的環境變數; 現在想將所有變數一次清除:unset $(env | grep -i tw | sed 's/=.*//')
- all.txt 檔案裡面列有許多檔名。 希望將這當中所有的圖形檔搬到
image/ 目錄下:
mv $(file $(cat all.txt) | grep -i image | sed 's/:.*//') png
- 在 ubuntu 底下, 想查看所有 wiki 軟體的說明:
apt-cache show $(apt-cache search wiki | grep -i wiki | grep -v '^lib' | sed 's/ - .*//') > wiki.txt
- 下了許多 wget -nv ... 指令, 到一個慢速網站抓檔。 不小心把 screen 關掉了。 把尚未抓完的檔名放到 a, 把 history 放到 b, 然後 for f in $(cat ~/a) ; do grep $f ~/.history ; done > ~/c
類似文章
- 本頁最新版網址: https://frdm.cyut.edu.tw/~ckhung/b/gnu/combination.php; 您所看到的版本: November 12 2020 14:45:01.
- 作者: 朝陽科技大學 資訊管理系 洪朝貴
- 寶貝你我的地球, 請 減少列印, 多用背面, 丟棄時做垃圾分類。
- 本文件以 Creative Commons Attribution-ShareAlike License 或以 Free Document License 方式公開授權大眾自由複製/修改/散佈。