MacGyver |
---|
Unix 自70年代問世以來風行於世,從大大小小各種多人多工的
電腦系統中脫穎而出,深受系統管理者及玩家之喜愛,
其中非常重要的原因之一是:因為 Unix 具備
不錯的軟體工具及環境,可讓使用者很方便的組成各種各樣的工具,
可以大幅提高工作效率。
如同電視影集裡的馬蓋先,經常利用手邊毫不起眼的工具或物品,
運用簡單的物理原理組成非常好用的救命武器或工具。
而我們如能善用 Unix 提供的環境及基本的工具也能利用
簡單的指令組成強大的高階指令(應用程式),不需
使用C/C++/Java等語言辛辛苦苦的撰寫程式。
此種程式設計環境因為都以 shell
作為最主要的語言,故俗稱為「shell programming」, 除了shell
之外,常用的程式工具為 sed, awk, ex,
perl。而用於產生網頁的工具程式 PHP也大量運用了Shell programming
的特色。
|
筆者使用 Unix 凡二十餘年,在電腦上寫論文、處理資料、
交換 Email、製作HTML投影片、改作業、打分數、等等
許多繁瑣的工作中,很高比例的工作均能藉由 Shell Programming
強大的能力快速解決。
雖然桌上的電腦仍然是跑微軟視窗,但最常開的軟體卻是
telent、Firefox browser 及一個 Unix emulator
(亦即在視窗系統上執行一個程式,創造一個虛擬的 Unix 環境)。
大部分的工作 是透過telnet 在Unix server 上完成的,
而處理個人電腦裡的檔案
也是經常使用Unix emulator 去做的。視窗系統與Unix 搭配使用,
成為最佳的工作模式。筆者的教學網頁裡數以萬計繁複的網頁,就是
憑著 vi (a text editor) 加上 shell script 獨力完成的,不需使用
Frontpage 或 Dreamwaver 等網頁製作軟體。
(其實,如果使用網頁製作軟體製作網頁,雖然可以手工製作非常
漂亮的網頁,可是人工成本太高了)。
在這裡,筆者先介紹幾個
小例子以展示 Unix shell script 的能力,再來談談一些經驗作為
引玉之磚。
(請注意:本文所提供的小程式只能當成「私房菜」,
做為個人的私有工具。如欲供大眾使用,則需更為嚴謹的設計。)
|
以下的指令將以檔名為 Image 開頭的 JPG 影像檔全部更改檔名,在
原檔名之前加上"nccu"字串。
|
如同一般的程式語言一般,要完成一樣事情並非只有一種方法,但多半
使用類似的演算邏輯。
Shell programming 可以使用的演算邏輯卻遠非一般程式
語言可比。Shell 有很多「巧門」,如能善用這些巧門的話,將可創出許多
的演算邏輯,可以省下許多編撰程式的時間。
例如:如要產生 1 至 1000 的數字,
一般人很自然的想到用迴圈(loop)的方法,使用 C/C++/Java
等程式語言撰寫一個程式,經過編譯與執行,得到一支程式。
以下是利用迴圈方式所寫的一個 C 程式:
如果你常用 cut 這個指令的話,這個方法只需構思數分鐘,再花個數秒鐘 直接從鍵盤鍵入指令,就可輕易得到結果。 如果你對 awk 熟的話,下面這個方法更為簡單:
|
如果對 awk 或特定工具程式不熟也無傷大雅,反正條條大路通羅馬,
前面兩種方式也可做到同樣的事。
|
以上小例子看似簡單,但它可是一種另類的程式,完全不用迴圈。
讀者可發揮無限的想像力發掘更多的巧門。
對於一般非專職程式設計師的使用者而言,使用
head、cat、cut 等這些常用指令遠比寫一個 C/C++/Java
程式更為熟練,所花的心力通常微不足道。二十餘年來,筆者
經常隨手花個數分鐘時間寫個shell script 幫忙處理瑣事,省下
不少時間。由於所費時間不多,通常不需刻意保存所設計的script,
絕大部分僅用過一次就丟掉,下次有需要時,重新再寫一次還
比花時間去找留存的shell script還更省事,只有時常會用到的script才
有留存供重複使用的價值。再者,小小的程式,要瞭解非常容易,很可能
比閱讀程式的註解還容易,所以很多程式連註解都是多餘的了。
當然,如果要設計一個大型的程式,還是必要規規矩矩的按部就班
去撰寫程式以及加入註解。
|
要具備善用 Unix 的功力的話,傳統的程式訓練是不夠的,
必須對Unix 的環境及各種工具程式的特性有相當深入的瞭解,
尤其是對於用來組合各種工具程式的程式─shell,更需有透徹的瞭解。
|
Unix 之優缺點 |
---|
任何一種程式語言都有其最適用的情況及其罩門,Unix shell Programming 也
難逃此宿命。它有幾項優點:
|
1. Script 都是純文字檔,不被特定軟體綁住
| 大部分的檔案都是以文字檔存放,這是非常開放的系統,檔案之間的分享 非常方便,一個程式所產生的檔案很容易為其他程式使用,一個程式 在使用其他程式所產生的檔案時,也不需知道是何種程式所產生的。 比起現行個人電腦視窗系統上的各種使用專屬格式的應用程式而言, 方便很多。
2. 不需編譯,非常容易移植到不同的 Unix 系統下執行
| | shell/awk/sed/ex/perl script 都是純文字檔,也不需 編譯即可使用,非常方便,從一個系統移植到另一系統時,直接 搬過去即可,雖然可能要更動有些系統設定,但是因為不需重新 編譯,可省下不少麻煩。
3. 適合用於開發簡易小軟體
|
| 很多script 長度很短也很簡單,是所謂的 "little program"。 當設計一個專供個人使用的 script時, 幾乎不需另外寫使用手冊,直接看script 就可以瞭解其用法。 要維護也很簡單,不需撰寫複雜的維護手冊或設計手冊。 當然,如果是要寫一個供公眾使用的 script 時,這些囉唆的 額外工作還是要按部就班去做的。
4. 因開發耗時極短,玩家可隨時根據自己的需求動手開發或更改
|
| 如果是專供個人使用的 Script,當然可以隨意的根據自己的需要設計, 反之,如果是使用他人提供的程式時,不但無法完全符合個人需求, 使用者還須花時間去尋找適用程式,更須花時間去 K 使用手冊。 很多時候,還不如自己寫個 shell script,不但更省時間, 也更符合自己的需求。 |
---|
缺點當然是免不了:
|
1. 執行效率較差
| Shell 因為是用 Interpreter 而且是用間接的方式達到目的 (除了程序控制的指令之外,大部分都是叫用 UNIX 的既有程式來執行), 其執行效率不佳。例如,前面所舉的數字產生器,如果是用head, cat, cut 去組合成的話,因為這三個指令是三個不同的程式,呼叫起來要耗費 相當長的時間 (豪秒範圍), 比傳統的 C/C++/Java 的迴圈方式慢很多。 可是,話說回來,終端機前的使用者對於0.001 秒與數秒的反應時間 根本無法察覺差異,即使可以察覺差異,差別也不大。 反而是構思與程式設計所花時間較長, shell script 的設計通常可以省下數小時甚至數天的設計時間, 那差別可大了。程式的執行時間雖然長了數秒鐘,但可節省數小時 的設計時間,對於個人使用的小程式而言,這筆買賣太划算了。
2. 力有未逮之時
|
| Shell 畢竟不是傳統的 general purpose 的程式語言, 有些事是做不到或很難做的,例如,在shell裡進行數學運算 就很麻煩,所以不可能作為大型軟體 的主要開發語言。所幸,後來發明的 perl 程式語言融合了 shell script 及傳統程式語言的優點,其能力已經不下於傳統的 程式語言,現在很多大型公用軟體都是使用perl去撰寫的。 此外,shell script 可以很方便的處理文字檔,但對於非文字檔 及多媒體檔等就很不方便,例如處理微軟的 Winword 所產生的 doc 檔,那就無能為力了。在處理多媒體檔案時,常需用到硬體的 驅動程式,而不幸的是,系統不一定有提供驅動程式的介面。
3. 漏洞難免
|
| 由於設計給個人用的程式不免為了省時省事而忽略了很多 意外的處理,使用不慎時會有嚴重後果,必須非常小心,尤其是 當script 有涉及檔案的更動時,更須特別小心。 話說回來,如果設計用完即丟的小程式時也要將所有意外情況都考慮清楚, 那也省不了多少設計時間,也就失去了原有 little programming 的立意。 有得必有失,得失之取捨,得由使用者視情況決定。 |
---|
#2 Fast tool building #2 Robust #2 ASCII files #3 Interoperability #3 Portable #3 Sharable (in NFS) #3 Easy to maintain/understand #3 Little documentation overhead #3 Save storage space #2 No learning time, no need to read manual #2 Know all the shortcomings # #.bp bad Bad Problems #2 Resource Intensive #3 consume many processes and I/O #3 Slow #2 Not a general purpose programming language #2 May not cover all exceptions #3 trade-off between coding time and robustness |
---|
學習 Unix Shell Programing 之方法 |
---|
1. 熟悉 Unix 上各種基本指令及小型工具程式
| 市面上有很多書,網路上有很多教學網站可以去挖,筆者的教學網站 (www.cs.nccu.edu.tw/~lien/UNIX.htm) 也有一些資料,如今的資訊專業人員可以很輕易的挖出來。 有用的小型工具程式 (little programming language) 包括 shell, sed, awk, ex 等。 此外,perl 是一個更高級的programming language, 很多要 利用好幾個程式工具合作才能完成的事,都可以輕易的在perl中解決。 但是,因為perl 包含了很多 shell/awk/sed 的功能,也比較繁瑣, 最好等歷練過shell/sed/awk/ex 這些之後才來學 perl 會比較 容易上手。最後,如果要製作含有 CGI 的網頁時,學學PHP 等專為CGI 設計的語言,也是很重要的。
2. 盡量熟悉 Regular Expression
|
| Regular Expression 是 shell programming 之所以非常 強大的關鍵之一,在 awk/sed/ex/vi 都有相容的 regular expression, 使用者務必盡早熟習,對於受過正統資科訓練的人而言,熟習regular expression 並非難事。
3. 熟悉各種特殊符號及其用法
|
| 每一個工具程式都會有一些特殊符號,例如regular expression 就有很多符號, 當一個script 是叫用多個 工具程式時,這些特殊符號必須使用層層的escape符號來配合。 Shell script 的內容會變得非常奇怪,難以解讀。使用者必須有 能力克服這個困難才能盡情發揮shell script 的功能。 在設計shell script 的過程中,最常碰到的難題多半是因為特殊符號處理不當。
4. 熟悉 Unix 上各種系統檔案的路徑
|
| 例如:/bin, /tmp., /etc. /usr/spool/mail, /usr/bin 等, 至少我們可以加以運用,在我們舉出來的實例中, 就有利用到spell 所用的字典檔案來設計自己的script的。 所幸,這些路徑比起微軟視窗系統的登錄檔簡單許多,不難記住。
5. 熟悉 Unix 基本精神
|
| 例如 directory 及 device driver 在Unix中均視為檔案,其管理方式 就像管理檔案差不多。例如:我們可以利用這種特性,輕易的執行簡單的 Instant Message 功能。
6. 熟悉 Unix 程式設計的一些習慣,並盡量配合
|
| 例如: 而所有產生的資料盡量由 STDOUT 輸出,以方便組合成其他指令。 如果該指令可用來用在 "|" 管道之中的話, 其資料盡量由 STDIN 輸入,這應由使用者自己拿捏。 |
---|
Shell Script 設計小秘訣 |
---|
1. 定期備份,隨時備份要更改的檔案
| 最重要的是系統要定期備份, 越方便能力越強的系統,其破壞力也越強大。 例如: 如果某個使用者下一個如下的指令要清除一些檔案:
2. 慎重選用適當的工具程式
| | 雖然是條條道路通羅馬,但是各種工具程式各有其特性, 使用者最好瞭解各種工具程式的特性,再據以挑選適當的工具來用。 選用適當的工具會讓你事半功倍,否則可能是自找麻煩。
3. 盡量自動化
| | 只要能自動化就自動化(能偷懶就偷懶),讓shell 負責執行繁瑣的重複性工作。
4. 不要勉強自動化
| | 不要為自動化而自動化,有時候直接用手去做反而更快。
我們所舉的例子中,就有要求使用者進入vi 去做事的, 並非全部交由shell自動去做。 不過,為了磨練shell programming 的技巧,有時候 難免多花點時間找點苦頭吃,也是不錯的。
5. 適時搭配 PC 視窗系統
| | 如果搭配視窗系統去作比較方便時,那就不要硬在Unix上作。 視窗系統絕對有其優點,跟 shell programming 搭配使用 ,將可發揮 相輔相成之功效。
6. 追求整體時間的節省
|
| 通常在處理一件事,例如資料轉換,或整理照片檔案時,牽涉到眾多的雜事, 諸如輸入資料,編輯輸入檔,反覆執行 script 等,在設計script 時,需注意到各方面都需節省時間,假設一個寫得很好效率很高的script 卻需要花很多時間準備資料,那就得不償失了。相反的,如果追求輸入資料 的方便,卻讓 script 的撰寫礙手礙腳,也是不好。此外,也需顧及維護的 方便性,有時候寫得太過機巧的 script 若無適當的說明,在後日需要維護時,卻很難理解,那不美了。這些觀念, 在軟體工程的課程都有說明,讀者可參考之。 總之,設計 script 時方方面面都需兼顧,追求整體工作時間的節省。 |
---|
#1 Use right tools in right configurations # #1 Keep it simple and stupid # #1 Don't use hand #2a #Don't use hands to do things that can be done efficiently by #the computer. -- Tom Duff #2b #1 Don't use computer #2a #Don't use computer to do things that can be done efficiently #by hand. -- Richard Hill #2b #2 Treat exceptions manually if too much trouble #1 Be familiar with regular expressions #1 Pay special attention to escape sequences |
---|