shell十三問(三)
來源:互聯網
上載者:User
11.5
噹噹當~~~ 上課囉~~~ ^_^
前面提到:$ cat < file >; file 之後原本有內容的檔案結果卻被洗掉了﹗
要理解這一現像其實不難,這隻是 priority 的問題而已:
* 在 IO Redirection 中,stdout 與 stderr 的管道會先準備好,才會從 stdin
讀進資料。
也就是說,在上例中,>; file 會先將 file 清空,然後才讀進 < file ,
但這時候檔案已經被清空了,因此就變成讀不進任何資料了...
哦~~~ 原來如此~~~~ ^_^
那... 如下兩例又如何呢?
CODE:[Copy to clipboard]$ cat <>; file
$ cat < file >;>; file
嗯... 同學們,這兩個答案就當練習題囉,下節課之前請交作業﹗
好了,I/O Redirection 也快講完了,sorry,因為我也只知道這麼多而已啦~~~
嘻~~ ^_^
不過,還有一樣東東是一定要講的,各位觀眾(請自行配樂~!#@!$%) :
---- 就是 pipe line 也﹗
談到 pipe line ,我相信不少人都不會陌生:
我們在很多 command line 上常看到的" | "符號就是 pipe line 了。
不過,究竟 pipe line 是甚麼東東呢?
別急別急... 先查一下英漢字典,看看 pipe 是甚麼意思?
沒錯﹗它就是"水管"的意思...
那麼,你能想象一下水管是怎麼一根接著一根的嗎?
又,每根水管之間的 input 跟 output 又如何呢?
嗯??
靈光一閃:原來 pipe line 的 I/O 跟水管的 I/O 是一模一樣的:
* 上一個命令的 stdout 接到下一個命令的 stdin 去了﹗
的確如此... 不管在 command line 上你使用了多少個 pipe line ,
前後兩個 command 的 I/O 都是彼此串連的﹗(恭喜:你終於開竅了﹗ ^_^ )
不過... 然而... 但是... ... stderr 呢?
好問題﹗不過也容易理解:
* 若水管漏水怎麼辦?
也就是說:在 pipe line 之間,前一個命令的 stderr 是不會接進下一命令的
stdin 的,
其輸出,若不用 2>; 導到 file 去的話,它還是送到監視器上面來﹗
這點請你在 pipe line 運用上務必要注意的。
那,或許你又會問:
* 有辦法將 stderr 也喂進下一個命令的 stdin 去嗎?
(貪得無厭的傢伙﹗)
方法當然是有,而且你早已學過了﹗ ^_^
我提示一下就好:
* 請問你如何將 stderr 合并進 stdout 一同輸出呢?
若你答不出來,下課之後再來問我吧... (如果你臉皮真夠厚的話...)
或許,你仍意尤未盡﹗或許,你曾經碰到過下面的問題:
* 在 cm1 | cm2 | cm3 ... 這段 pipe line 中,若要將 cm2
的結果存到某一檔案呢?
若你寫成 cm1 | cm2 >; file | cm3 的話,
那你肯定會發現 cm3 的 stdin 是空的﹗(當然啦,你都將水管接到別的水池了﹗)
聰明的你或許會如此解決:
CODE:[Copy to clipboard]cm1 | cm2 >; file ; cm3 < file
是的,你的確可以這樣做,但最大的壞處是:這樣一來,file I/O 會變雙倍﹗
在 command 執行的整個過程中,file I/O 是最常見的最大效能殺手。
凡是有經驗的 shell 操作者,都會盡量避免或降低 file I/O 的頻率。
那,上面問題還有更好方法嗎?
有的,那就是 tee 命令了。
* 所謂 tee 命令是在不影響原本 I/O 的情況下,將 stdout 複製一份到檔案去。
因此,上面的命令列可以如此打:
CODE:[Copy to clipboard]cm1 | cm2 | tee file | cm3
在預設上,tee 會改寫目標檔案,若你要改為增加內容的話,那可用 -a 參數達成。
基本上,pipe line 的應用在 shell 操作上是非常廣泛的,尤其是在 text
filtering 方面,
凡舉 cat, more, head, tail, wc, expand, tr, grep, sed, awk, ...
等等文文書處理工具,
搭配起 pipe line 來使用,你會驚覺 command line 原來是活得如此精彩的﹗
常讓人有"眾裡尋他千百度,驀然回首,那人卻在燈火闌珊處﹗"之感... ^_^
....
好了,關於 I/O Redirection 的介紹就到此告一段落。
若日後有空的話,再為大家介紹其它在 shell 上好玩的東西﹗bye... ^_^
-------------------------------------------------------------------------------------------------
12) 你要 if 還是 case 呢?
放了一個愉快的春節假期,人也變得懶懶散散的...
只是,答應了大家的作業,還是要堅持完成就是了~~~
還記得我們在第 10 章所介紹的 return value 嗎?
是的,接下來介紹的內容與之有關,若你的記憶也被假期的歡樂時光所抵消掉的話,
那,建議您還是先回去溫習溫習再回來...
若你記得 return value ,我想你也應該記得了 && 與 || 是甚麼意思吧?
用這兩個符號再配搭 command group 的話,我們可讓 shell script
變得更加聰明哦。
比方說:
CODE:[Copy to clipboard]comd1 && {
comd2
comd3
} || {
comd4
comd5
}
意思是說:
假如 comd1 的 return value 為 true 的話,
然則執行 comd2 與 comd3 ,
否則執行 comd4 與 comd5 。
事實上,我們在寫 shell script
的時候,經常需要用到這樣那樣的條件以作出不同的處理動作。
用 && 與 ||
的確可以達成條件執行的效果,然而,從"人類語言"上來理解,卻不是那麼直觀。
更多時候,我們還是喜歡用 if .... then ... else ... 這樣的 keyword
來表達條件執行。
在 bash shell 中,我們可以如此修改上一段代碼:
CODE:[Copy to clipboard]if comd1
then
comd2
comd3
else
comd4
comd5
fi
這也是我們在 shell script 中最常用到的 if 判斷式:
只要 if 後面的 command line 返回 true 的 return value (我們最常用 test
命令來送出 return value),
然則就執行 then 後面的命令,否則執行 else 後的命令﹔fi 則是用來結束判斷式的
keyword 。
在 if 判斷式中,else 部份可以不用,但 then 是必需的。
(若 then 後不想跑任何 command ,可用" : " 這個 null command 代替)。
當然,then 或 else 後面,也可以再使用更進一層的條件判斷式,這在 shell
script 設計上很常見。
若有多項條件需要"依序"進行判斷的話,那我們則可使用 elif 這樣的 keyword :
CODE:[Copy to clipboard]if comd1; then
comd2
elif comd3; then
comd4
else
comd5
fi
意思是說:
若 comd1 為 true ,然則執行 comd2 ﹔
否則再測試 comd3 ,然則執行 comd4 ﹔
倘若 comd1 與 comd3 均不成立,那就執行 comd5 。
if 判斷式的例子很常見,你可從很多 shell script
中看得到,我這裡就不再舉例子了...