星期日, 9月 11, 2005

生理週期減重法 易瘦日班

生理週期減重法 易瘦日班
http://denniswave.dyndns.org/MT/archives/Diet/000013.html#more

無意間看到此資料, 供女性朋友看....

改變食物的選擇

改變食物的選擇

對同樣食物只要略為挑選它的形式及製作方法,所攝取的熱量可以大為減少。

From:http://www.enutrition.com.tw/AT_body/body_fat_food.htm

* 先去除雞皮、鴨皮、肥肉,只吃瘦肉的部份。  

* 選擇帶骨帶殼的肉類及水產吃
帶殼的蝦使你必須慢慢一隻一隻地撥去殼再吃,沒有辦法像吃蝦仁那樣一湯匙一湯匙地吃得又快又多。同樣的,盡可能少吃絞肉製品,如漢堡、肉丸或獅子頭等,它們的肥肉量多且容易一下吃太多,帶骨頭的肉或雞鴨肉不致於讓你三兩口吃進一大塊。

* 盡量不要選大塊的魚肉或魚排,選擇帶刺的整條魚
因為你必須剔除魚刺,吃的速度自然就慢下來了。  

* 盡量少選擇大塊的肉類如牛排或豬排等,多選擇肉絲類的半葷素菜
一大塊肉至少有四兩至半斤,若切成絲,一大盤肉絲菜,足夠全家人吃。  

* 盡量避免油炸的食物
尤其是沾了粉油炸的食物,吸油量很高,所含的熱量常比油炸的同樣食物高出兩倍。無法避免時,先去掉外皮再吃。

* 芶芡的食物,乾挑內容物吃,不喝芶芡汁。  

* 吃新鮮水果但少喝果汁
一口氣喝下一杯柳丁汁與一片一片的慢慢吃,後者使你更有滿足感,而實際吃到的量卻較少(一杯柳丁汁至少要三到四個柳丁榨成)。葡萄一粒一粒慢慢剝皮吃,蘋果削皮一片一片插吃著;多子的小西瓜會令你花較多的時間去吃。

抓出4個破壞腰臀S的元兇

抓出4個破壞腰臀S的元兇

雖然隨著年齡增長,體內新陳代謝會減緩、身材曲線也會漸漸向下發展,但是不可否認,有很多生活習慣,都是加速不完美體態提早出現的原因。改善以下4種不良行為,絕對有助保持完美腰臀曲線。

From:SHAPE秀雜誌國際中文版


S killer:經常以澱粉類為主食,也捨棄不掉炸雞、薯條等油炸食物.......
雖然以澱粉類為主食的東方人,與東方人多有的下半身肥胖不能完全畫上等號,不過熱量高的澱粉類、油炸類食物,過多攝取,對脂肪細胞多集中在腰腹臀腿部位的女生來說,實在有發展成局部肥胖的可能。均衡飲食,避免高熱量、高脂肪的攝取,對養生、美身來說,都是一大幫助。


S killer:愛穿時下流行的鬆垮低腰褲.....
流行已經一、兩年的鬆垮低腰褲,妳也趕這股風潮嗎?小心寬鬆的低腰設計,助長了腰腹間的贅肉恣意發展,而變得突出、鬆垮。服裝及貼身衣褲的正確選擇與穿著,可有效幫助維持或掩飾身材,實在需要慎選。


S killer:吃完飯後馬上又坐進椅子、沙發中,繼續工作、看電視.....
算起來,這應該是小腹婆們最常做的動作之一。吃得飽飽的,卻又馬上窩在沙發裡看電視,或者坐回電腦螢幕前繼續工作。長時間久坐,不僅多餘熱量消耗不掉,多半還會累積在容易發胖的腰臀部位,如此生活作息,想要擁有S曲線實在很難。


S killer:缺乏運動,連多走路的習慣都沒有....
發現沒,有運動習慣的人通常很少有扁屁股喔!運動的時候可以鍛鍊到全身肌群,外觀上線條會變得緊緻結實,內在則讓新陳代謝保持在良好狀態,不僅S曲線有了,也比較不容易發胖。

Diet-04.png

清除宿便的好方法-海鹽

清除宿便的好方法-海鹽

清宿便的好方法 我的瑜珈老師告訴我們一件神奇的事: 一個不花淺清腸、清宿便的方法,可以讓你健康、皮膚變好、甚至可以減肥的好方法,我試過有用哦。

From:http://c2s.phmhs.phc.edu.tw/89/104/%A4%E5%B3%B9%B3%A1.htm

一、首先在你舒適方便的時間,且必須一早空腹。

二、然後準備自然鹽(即海鹽),兩個一截大姆指多的量。

三、先用適量熱開水將鹽打散,再加入500cc冷開水後,不多想的一口氣的順順的喝完它。

四、不用多想改變份量或次數,順順的喝,若有做噁,喝完後可吃東西止噁,此時你肚子是臌臌的。

五、經過40分~1小時多,你就會將你剛所喝的加上你肚子?的宿便一瀉千里、一拉而空、一股腦的頃肚而出,但你是不覺得肚子痛的,你會見到你這輩子最多的便便。

六、你會覺得這是你下輩子的体重。

七、最好一個星期行使一次。

于美人消脂茶

于美人消脂茶

于美人〔圓滿計劃〕節目中介紹的幾組消脂茶。效果驚人!不試可惜!

1. 玫瑰蜜棗茶:有效清除腸胃宿便,再嚴重的便秘問題皆可穫得改善!
2. 窈窕美腿茶:改善下半身肥胖(虛胖水腫型效果更佳)
3. 纖美瘦身茶:可保養調養身體,有效去除油脂,適合膽固醇過高者

From:http://www.sunrich.com.tw/Health/DIY/WeightControlTeaFromMrsYu.php

玫瑰蜜棗茶(成份:加州蜜棗.粉紅玫瑰)

清除腸胃宿便,保證一杯見效!輕輕鬆鬆就能擁有輕盈體態。

此道茶結合玫瑰的清香與蜜棗的甘甜,口味芬芳好入喉,長期飲用可消脂瘦身,有效去除體內油脂,清除腸胃宿便,改善內分泌失調,還能調理血氣,嬌嫩肌膚,消除疲勞,舒緩神經緊張。平日當茶飲用效果更佳!(冰涼後風味尤佳)只要每天飲用一杯(500cc),輕鬆享瘦效果看得見!(二星期2?3公斤)

★備註說明★ 效果驚人!真的不試可惜!

玫瑰蜜棗茶強調其〔清除腸胃宿便〕之功效,通常於飲用後約一至二個小時內便會開始大量排便(宿便越多者排得量越多),到最後排出的污物僅剩污水時,整個〔清除腸胃〕的工程就差不多了!體內的宿便越少,人也會越健康,不僅氣色變好,臉色紅潤有光澤,減少了一堆體內不必要的東西,當然也就會變瘦囉!

玫瑰蜜棗茶的作法

材料:加州蜜棗5顆,粉紅玫瑰一小搓即可(最好是買已經打碎的,比較能沖煮出味道)

作法:

1. 準備500-600CC的水將蜜棗跟粉玫瑰都放進去。

2. 放在爐火上加熱到滾熄火即可。

From:http://www.nico.com.tw/doctor/new_page_227.htm

玫瑰,具有疏肝解鬱的作用,對於保護肝臟,促進新陳代謝,強效去脂的作用(但他所去的油脂只是腸胃道的油脂,而不是已經存在皮下的皮下脂肪)。

蜜棗,可提供纖維質。長期飲用的話,可去清除宿便,維持新陳代謝的功能正常,當然就能讓皮膚看起來細嫩,而且也不容易在體內堆積肥有,可達到減肥的效果。

玫瑰雖然有去脂的作用,但也不要一次弄得太多太濃,不然會有腹痛、水瀉的情形的情形。初期可以一天飲用一杯杯,天天使用,等到宿便被清除的差不多就可以把間隔時間拉長,一星期喝一兩次就可以了。

注意:

事實上,這類會造成腹瀉效果的茶,都不適合長期連續的飲用,雖然拉完了會讓你覺得體重比較輕,但長時間飲用容易造成營養吸收不良,尤其是對於脂溶性維生素A、D、E、K容易流失,還會有脫水的危險,這樣就算瘦了還是會瘦得乾乾癟癟。

窈窕美腿茶(成份:檸檬馬鞭草.迷迭香.檸檬草)

平日當茶飲用,可有效消除下半身肥胖,減少肌肉組織多餘水份滯溜。

檸檬馬鞭草:又稱檸檬葉,可減緩靜脈曲張、腿部水腫,消脂瘦身,腸內淨化抗神經衰弱,緩和經痛,皮膚病症,改善偏頭痛(孕婦不宜)。

迷迭香:增強記憶力,提神,並可去斑,減少皺紋,消除口臭,偏頭痛,神經痛,強化肝腎及心臟功能,改善經痛(孕婦不宜)。

檸檬草:可健胃、利尿、防止貧血並滋潤肌膚,消除脹氣,提神。

纖美瘦身茶(純天然中藥草本植物 絕無添加西藥或防腐劑)

玫瑰纖美瘦身茶係由上選玫瑰花、決明子、仙楂、甘草、陳皮等純正中藥材所調配而成,不苦不澀,藥性溫和且不傷胃,玫瑰香中略帶一股清甜,清清爽爽的口感,飲用時氣味芬芳好入喉。平日當茶飲用(冷熱飲皆可)效果尤佳!可減少腸胃宿便及大魚大肉後產生的油脂(不會有腹瀉等症狀)。一個月正常約減3- 6KG。

【成份】

玫瑰花:消脂瘦身.嬌嫩肌膚.消除疲勞.改善內分秘失調並調理血氣。

決明子:潤腸通便、清肝明目、降血脂。

仙 楂:消食消脂,促進胃液和胰液分泌。

陳 皮:健脾化痰、促進胃液分泌。

甘 草:補氣解毒。

薄荷葉:消除口臭,整腸健胃,提神醒腦。

排解宿便小秘方

排解宿便小秘方

宿便一直累積在小腹,就會讓小腹顯得很大,所以也有人說清除宿便可以減肥,因為小腹就會消失了嘛!姑且不論減肥的效果,要是可以讓自己不再便秘、輕鬆排除便便,就已經是人生一大樂事了呢!

From:http://www.quixtar.idv.tw/story/story_display.php?no=1735&kind=2

*玫瑰蜜棗茶:
曾經在于美人的圓滿計劃中被大大的推薦唷!只要加洲蜜棗與粉紅玫瑰就可以有效清除腸胃宿便,再嚴重的便秘問題也能獲得改善呢!長期飲用的話還可以消脂瘦身,有效去除體內油脂,改善內分泌失調,還能調理血氣,消除疲勞,舒緩神經緊張等這麼多好處,平日當茶飲用效果會更好喔!

玫瑰蜜棗茶的作法

材料:加州蜜棗5顆,粉紅玫瑰一小搓即可(最好是買已經打碎的,比較能沖煮出味道)

作法:

1. 準備500-600CC的水將蜜棗跟粉玫瑰都放進去。

2. 放在爐火上加熱到滾熄火即可。

From:http://www.nico.com.tw/doctor/new_page_227.htm

玫瑰,具有疏肝解鬱的作用,對於保護肝臟,促進新陳代謝,強效去脂的作用(但他所去的油脂只是腸胃道的油脂,而不是已經存在皮下的皮下脂肪)。

蜜棗,可提供纖維質。長期飲用的話,可去清除宿便,維持新陳代謝的功能正常,當然就能讓皮膚看起來細嫩,而且也不容易在體內堆積肥有,可達到減肥的效果。

玫瑰雖然有去脂的作用,但也不要一次弄得太多太濃,不然會有腹痛、水瀉的情形的情形。初期可以一天飲用一杯杯,天天使用,等到宿便被清除的差不多就可以把間隔時間拉長,一星期喝一兩次就可以了。

注意:

事實上,這類會造成腹瀉效果的茶,都不適合長期連續的飲用,雖然拉完了會讓你覺得體重比較輕,但長時間飲用容易造成營養吸收不良,尤其是對於脂溶性維生素A、D、E、K容易流失,還會有脫水的危險,這樣就算瘦了還是會瘦得乾乾癟癟。


*枸杞茶:
這是能夠消除便秘的特效茶喔!可以將頑固的宿便一舉排出,也能夠消除疲勞,在幫助排出宿便後,還能夠使身體恢復正常的循環呢!
枸杞雖然是一種中藥,但卻沒有特殊的苦味。在晚上的時候多喝一點,隔天早上如廁後保證你神清氣爽啊!

很有趣的排除宿便呼吸法?
這個方法可以消除腹部贅肉、治療便秘、清除宿便喔!可以試試看..

1.在地板坐下,左右腳心相對,左手握住左腳板,大拇指置於腳掌心,其餘4指置於腳背,右手亦然。坐好後,慢慢深吸口氣,閉氣約5秒。

2.吐氣時,將上半身慢慢往前傾,盡量碰到地板。然後上半身慢慢抬起,緩緩吸氣。

3. 重複這個動作10分鐘或是到產生便意為止。

其實呢,我們的飲食不正常、太油膩也是造成排便不易的最大原因,可以多吃一些、蔬菜水果,足夠的運動量,這些都可以讓你每天都順順利利的唷!

用ipfw限制網路卡卡號上網

用ipfw限制網路卡卡號上網

1. 先要有ipfw2,因為只有ipfw2可以鎖 mac address.
但前提是要把ipfw2 compile進 kernel裡.
再重新compile /sbin/ipfw (make -DIPFW2)
kernel config file --> options IPFW2
/etc/make.conf --> IPFW2?=TRUE

2. ipfw 設定:
假設要允莧A:AA:AA:AA:AA:AA BB:BB:BB:BB:BB:BB CC:CC:CC:CC:CC:CC
這三台卡號的電腦通過, 其餘不給過, 就用
arp -s 192.168.0.10 AA:AA:AA:AA:AA:AA
arp -s 192.168.0.11 BB:BB:BB:BB:BB:BB
arp -s 192.168.0.12 CC:CC:CC:CC:CC:CC
設定static arp, 然後再用ipfw設定
全部允許:
ipfw add 00100 allow any to any via lo0
ipfw add 00110 allow any to any via (對外介面)
限制連外:
ipfw add 00120 allow me to 192.168.0.0/24 via (對內介面)
ipfw add 00200 allow 192.168.0.10 to me via (對內介面)
ipfw add 00201 allow 192.168.0.11 to me via (對內介面)
ipfw add 00202 allow 192.168.0.12 to me via (對內介面)
ipfw add 01000 deny 192.168.0.0/24 to me via (對內介面)

如此一來就只有該卡號且用該IP的電腦才能通過

消除檔案中的^M

消除檔案中的^M

cat filename | tr -d ' ' > newfile

開放性原始碼的下載站點

開放性原始碼的下載站點

1.http://sourceforge.net/
特點:排列下載排名很清楚

2.http://freshmeat.net/
特點:搜尋的功能比上面那個細

3.http://www.scriptdex.com/

4.http://www.scripts365.com/

5.http://jancw.dk/portal1/default.asp

6.http://php.resourceindex.com/

7.http://www.devshed.com/

8.http://www.hotscripts.com/

9.http://www.silkphp.com/

10.http://www.phpx.net/

Mysql備份

Mysql備份

mysqldump -uID -pPWD -A > mysqldump.sql
-u帳號
-p密碼
-A 所有資料庫

缺點:ps會看到密碼。

或是利用檔案直接複製備份。

Regular Expressions

Regular Expressions

作者: 朝陽科技大學 資訊管理系 洪朝貴

Regular Expression 是什麼? 有人直譯為「常規表示式」; 筆者偏好意譯, 姑且叫它「字串樣版」。它的功能是協助我們搜尋字串, 甚至對檔案內的特定字串做全面性的代換。 一般簡單的文字檔案編輯器 (例如 MS Windows 下的記事本, DOS 下的 edit 或是 Linux 下的 pico) 不支援 regular expression (以下簡稱 regexp), 所以我們在搜尋或代換字串時, 這些編輯器往往無法抓住我們的意思, 不是太寬鬆 (例如想找 port, 卻連 important 也找出來) 就是太嚴格 (例如想找 color, 卻遺漏了 colour)。 雖然大部分編輯器提供忽略大小寫等選項, 但所能解決的問題還是相當有限, 像上述兩個簡單的例子都沒有辦法解決。 如果改用 regexp, 則甚至可以處理諸如 "一份 html 檔裡面所有的 hyperlinks" 這類的複雜搜尋條件。

具體地說, 我們在想要搜尋的字串當中夾雜一些特殊符號, 指示電腦以較嚴格或較寬鬆的條件去搜尋, 這樣的字串就叫做 regexp。例如要找 modem 或 Modem, 我們可以用 [Mm]odem 這個 regexp 來表示。 這裡的方括弧就是 regexp 語法中的特殊符號之一, 代表裡面任何一個字元放在這一個位置都可以 (但總歸要是一個字元)。

Regexp 不是一套軟體, 而是一套規則。 從廿年前的 vi 編輯器, 到現在的 java 語言, 都可以使用上這套規則。只要有國中英文程度, 與幾小時的學習投資, 就可以學會 regexp, 這並不是資訊科系的專利; 但是它的知識價值卻比任何視窗軟體 (微軟視窗或 Linux X 視窗) 更長久, 因為它不會退流行, 而且你可以拿它來與其他知識發揮 組合相乘 的效果。 筆者特別呼籲擅長分析語句文法的英文老師, 與喜愛分析組合勝過死記的數理老師, 花一點點工夫認識 regexp。 Regexp 絕對不比英文的複合句, 數學的因式分解, 物理的運動學更困難。 請您給我幾個小時, 讓我證明給您看, 這, 才具有長遠的學習投資價值, 才應該是資訊教育的主體。為了臺灣的未來, 請幫忙將我們的下一代從 新舊版本自不相容的 MS Word 桎棝當中解救出來, 讓他們有機會跳出視框, 重新思考學習電腦的意義。
練習前的準備

在 freenix (例如 *BSD 或各種桌面版的 GNU/Linux) 底下學習 regexp 比較方便。 在這些系統裡面, 許多支援 regexp 的工具都是內建的, 不必另外安裝; 而且它們使用的資料檔多為開放透明的文字檔, 比較方便舉例。 當然 regexp 在 MS Windows 底下也可以使用 (如果花那麼多精神學習一套工具, 卻只能在一兩個作業平臺上使用, 未免太不划算!) 例如你的 Windows 系統內若裝有 perl, vi, 或 cygwin, 就可以用 regexp。 不過 windows 下到處都是 封閉的 .doc 檔, 無法發揮 regexp 的長處。

所以筆者假設你有一個 freenix 帳號可以使用, 並且不害怕學一點 命令列操作。 使用本講義的老師們, 如果不方便準備安裝有 freenix 的主機並開設帳號, 可以考慮發免安裝, 直接光碟開機即可使用的 knoppix 光碟給學生。 以下用 Mandrake 9.1 為例; 如果是其他版本, 命令下法完全一樣, 只有檔案與目錄的位置可能要調整一下。 例如前幾個實驗裡面用最多的 howto 文件, 在 Mandrake 底下, 放在 /usr/share/doc/HOWTO/HTML/en 裡面。

我們需要用到 less 來閱覽文字檔案, 也可能需要用到 lynx 文字瀏覽器將我網頁上的資料抓回你的帳號實驗。有時候我們下很長的指令, 如果你會用上箭頭把過去的命令叫出來改, 還會用 [TAB] 鍵讓電腦替你完成檔案名稱快打, 會方便很多。例如要進入上述 howto 文件的目錄, 可以這樣打: cd /usTABshTABdoTABHOTABHTTABen 這些都是 readline 使用者界面 所提供的功能。

支援 regexp 的工具很多, 但其中以 perl 的支援最為豐富, 所以本文拿 perl 作例子。 別緊張! 你不必學 perl。 我準備了三種句型:

1. perl -ne 'print if /.../' < 資料檔名
2. perl -ne 'print "$1\n" if /..(...)../' < 資料檔名
3. perl -pe 's/.../.../g' < 資料檔名

實驗時, 只要把其中一句話剪貼到你的命令列視窗上面再加以修改就可以了。 讀者只需要理解/專注在斜線之間的符號變化, 不必理會其他部分究竟是什麼意思。 當然 「資料檔名」 不要照抄; 檔名及路徑的 大小寫要完全照打; 單引號要成對。 Freenix 的 shell (接受/執行命令列的程式) 一板一眼, 堅持要求命令列上每個參數都要分清楚, 所以該留空格的地方, 就請務必留空格, 例如 -ne 與 -pe 的前後, 及檔案名稱之前的空格都不可以省略。

我們下的 perl 命令, 它要處理的資料, 可以有兩種不同的來源: (1) 靜態的文字檔, 像這樣: perl -ne '...' < 資料檔名 這裡的小於符號表示 "原本要從鍵盤上敲進去的資料, 改由資料檔讀入" (對我們所下的三種 perl 句型而言, 其實這個小於符號省略不寫也可以; 但解釋又不太相同。 為了解釋方便, 我們一律寫出。) (2) 由前一個命令動態即時印出來的資料, 像這樣: who | perl -ne '...' 這裡的直線符號, 念作 pipe, 意思是將前一個指令本來要印到螢幕上的資料, 直接餵給下一個命令當做輸入資料來吃, 彷彿用水管將兩個命令串起來一樣。 這兩種語法請不要搞混。 如果拿英文來作比喻, 資料檔名是名詞, 而命令是動詞, 第一種寫法是簡單句, 只有一個動詞; 第二種寫法是複合句, pipe 符號前後各有一個動詞。
英文文件跳著讀, 專業知識得來速

第一個例子要告訴讀者: 學 regexp 絕對不是資訊人的專利, 其他領域的朋友也能夠從這裡獲得許多好處。 今日的臺灣, 必須與國際社會接軌, 不論是財經/法律/管理/... 任何領域/專長的讀者, 都逃不掉要閱讀英文文件, 這其中有許多文件來自網路上, 本來就以純文字檔或 html 檔的形式存在。 我們希望可以在厚厚的一疊英文文件當中, 比同儕更快找到需要的資訊, 而不必老老實實地逐行閱讀完整的英文文件。 當然也希望不要因為馬虎搜尋而忽略掉太多相關的資訊。 這就是使用 regexp 的時機了。

話說回來, 筆者的知識局限在電腦, 所以就用電腦文件為例吧 :-) 請非資訊專長的讀者注意我們要搜尋的英文字串就好, 不要太在意順便提到的電腦知識。 從前剛開始學 Linux 的時候, 撥接上網出了問題。 我知道這個問題與 I/O port (輸入/輸出阜) 有關, 又知道可以到 howto 文件裡面去找答案, 所以就在 HOWTO-INDEX (所有 howto 文件的總索引) 裡面搜尋 "port", 看看有那一篇文件提到輸入/輸出阜: 先更換「目前工作目錄」到 /usr/.../en/HOWTO-INDEX 底下, 然後下: perl -ne 'print if /port/' *.html 這會將所有 html 文件當中, 所有提到 port 的那幾列給印出來。如果一下子印太多, 跳太快, 可以將印出來的結果丟給 less, 分頁印出來看比較清楚: perl -ne 'print if /port/' *.html | less 在 less 裡面, 還可以按 /portENTER, 就可以看到所有的 port 字串反白。 請按 G (大寫!) 跳到最後面, 看看總共抓到多少列 「含有 "port" 字串」。 最後按 q (小寫!) 離開 less。

顯然沒有抓到大寫的 Port。 可以改搜尋 /[Pp][Oo][Rr][Tt]/ 或者乾脆寫 /port/i 這裡的 i 是 ignore, 忽略大小寫差別的意思。 (好了, 我要開始偷懶, 不寫完整的指令, 只寫 /.../ 之間, 字串樣版在變化的部分; 當然你必須把完整的指令打出來。) 請再次在 less 當中搜尋 port, 跳到最後面看看抓到多少列, 再按 q 離開。 注意: perl 之前的搜尋動作 (目的在篩選過濾資料) 與之後在 less 裡面的搜尋 (目的在反白及移動遊標) 不相關。 如果注意看, 會發覺在 less 裡面, 大寫的 port 並未反白。 你可以在當初命令列上多放一個 -i, 像這樣: perl -ne 'print if /port/i' *.html | less -i 也可以在進入 less 之後才按 -i 鍵, 叫 less 也忽略大小寫。

但是, 怎麼連一點都不重要的 "important", 甚至是葡萄牙 (Portuguese) 都跑出來了呢? 其實我們要的 port, 是單獨出現, 完整的一個字。 我們希望 p 之前與 t 之後不要有其他英文字母 -- 希望它們出現在字的邊界。 請改用 /\bport\b/i 搜尋。 (這裡的 \b 相當於 less 裡面的 \< 與 \> ) 這次條件變得比較嚴格, 搜尋到的列數是否少了許多? 不過英文有個討厭的地方: 名詞有分單複數。 像這樣找, 複數的 ports 都被我們排除在外了。 沒關係, 請改用 /\bports?\b/i。 這裡的問號相當於 {0,1} 也就是 「前面的東西可以有, 也可以沒有」 的意思。請注意找找看是否多出一些複數, 搜尋到的列數是否又增加了呢? 至此, 我們找到了 「不嵌在其他字當中, 不管大小寫, 單數或複數的 "port"」。

後來在使用 PPP 撥接上網的時候, 又遇到撥接失敗, 但卻沒有錯誤訊息的問題。 有許多程式, 並不把錯誤訊息印在螢幕上, 而是印到檔案裡面, 這個動作叫做 log。 於是我到 PPP-HOWTO 裡面去搜尋 "log"。 還是一樣, 又找到一大堆 analogue, Catalogue 等等不相關的字。 再改用 /\blogs?\b/i 搜尋, 就好很多。 但是英文的動詞變化不只加 s, 還有現在分詞與過去分詞。 所以改搜尋: /\blog(|s|ged|ging)\b/i 這樣是否正確多了呢? 也請在 less 裡面搜尋 \ 反白看起來更清楚。 這裡的小括弧與 | 符號代表從多個字串中選一個: 我們要找的是 log, logs, logged, 或 logging. 請注意這比 [ ... ] 功能更強, 因為方括弧是: 從多個字元中選一個. 換句話說, 所有 [ ... ] 能做的事, 其實都可以用 ( ... | ... | ... ) 來做; 另一方面, 用小括弧與 | 來取代方括弧, 當然會比較囉嗦一些. 例如 [aeiou] 的效果和 (a|e|i|o|u) 一樣。
不要前後文, 只印出真正有興趣的部分

如果讀者真的操作上面的例子, 會發覺上節中 perl -ne 'print if /REGEXP/;' 這樣的句型會把含有 REGEXP 的一整列全部給列印出來. 如果我們只要 REGEXP 本身呢? 那就要用 (...) 和 $1, $2, ... 了。使用小括弧和「錢號數字」的組合, 可以圈選出我們有興趣的子字串, 並告訴 perl 我們只想印那幾對小括弧內的子字串。

上面的 perl 句型, 會將找到的字串 連同同一列上的前後文 一起印出。 但這樣並不方便, 因為有時候我們希望只印出真正有興趣的部分就好。 此時可以在 regexp 外面包一對小括弧, 然後稱之為 $1 將它印出來。 例如我們想分析 last -a 指令的輸出。 它印出過去一段時間內, 每個登入主機的人次。 如果想抓取 「星期幾」 欄位, 可以這樣下: last -a | perl -ne 'print "$1\n" if /\b([A-Z][a-z][a-z])\b/' 就像吃西式自助餐一樣, 只取我們真正有興趣的東西, 不要取而不用, 感覺更清爽。

請注意: 如果檔案內的一列上有兩個以上符合 regexp 描述的字串, 那麼這第二種句型只會印出每列上第一個符合條件的字串, 後面其他符合條件的字串都不會印出來。 例如我們要抓的如果是月份, 長相與星期幾一模一樣, 該怎麼辦呢? 搜尋時只好改成搜尋 「大小小空大小小」 (分別指 "大寫", "小寫", "空格"), 並且在第二串 「大小小」 外面加上一對小括弧就可以了。 請根據提示自己試試看。

又, 如果想同時印出月份及每次連線有多久, 例如:

ckhung :0 Sun Oct 26 20:51 - 21:54 (01:03)

應該如何寫呢? 與上一例 (抓月份) 相同, 雖然我們對「星期幾」沒有興趣, 但是它的長相與我們有興趣的字串相同, 我們不得不從它開始比對起: perl -ne 'print "Month: $1 Duration: $2\n" if /\b[A-Z][a-z][a-z] ([A-Z][a-z][a-z]).*\(([0-9][0-9]:[0-9][0-9])\)/' 這裡的 * 相當於 {0,無窮大}, 也就是說前面那個東西 ("任意一個字元") 可以重複出現 0 次, 1 次, 2 次, ... 任意次。 又, 因為小括弧在 regexp 裡面有特殊意義, 所以當我們真正對「小括弧字元」有興趣的時候, 前面必須加上倒斜線, 取消它的特殊意義。最後注意到 print 後面的字串其實隨我們高興愛怎麼印就怎麼寫, 不見得只能寫 $1 (當然如果用到 $2 $3 等等, 後面就必須真的有那麼多對小括弧才有意義)。

再例如我們想將 constants.txt 檔案裡面, 每列上出現的 (第一個) 數字抓出來。 先下一個簡單的 regexp 試試看: perl -ne 'print "$1\n" if /([0-9]+)/' constants.txt 這裡的 + 號相當於 {1,無窮大}, 也就是說前面那個東西 ("一個數字") 可以重複出現 1 次, 2 次, 3 次, ... 任意次。 諸如 {3,5} ? * + 等等符號, 功能都在重複前一串 regexp, 也稱為 quantifiers。 回到我們的例子, 這裡在抓 「連續出現的數字」。但是這樣只能抓到整數部分, 而且沒有正負號。 以下我們省略完整的命令, 只寫出 regexp, 逐步提高它的複雜度, 請讀者自行用上箭頭叫出前一個命令來修改, 並注意每次抓到的數字是否更加完整。

1. 因為 [0-9] 太常用到了, 在 perl 裡面有一個簡寫: /(\d+)/ 這裡的 \d 就是 digit "一個數字" 的意思。
2. 再考慮正負號 (但也可能沒有): /([+-]?\d+)/
3. 再考慮小數部分 (但也可能沒有): /([+-]?\d+(\.\d+)?)/ 注意第二個問號指的是前面小括弧內一整串 ("小數部分") 可有可無。
4. 最後考慮指數部分 (但也可能沒有): /([+-]?\d+(\.\d+)?([Ee][+-]?\d+)?)/

從這個例子, 我們也學到一個態度: 初學時, 別想要一步登天, 先從簡單的狀況處理起, 逐步修改到正確; 每修改一點, 就立即實驗一下。 另外, 錯誤訊息 是學習過程當中的至寶; 如果習慣性地忽略錯誤訊息, 學習的效果會非常差。

提到 perl 為常用 regexp 提供的簡寫, 還有 \w 表示 「一個文數字」 (word character), 等同於 [0-9a-zA-Z] 以及 \s 表示 「一個空白類字元」, 等同於 [ \t\n]。 這些簡寫只在 perl 的 regexp 裡面能用; 其他支援 regexp 的語言並沒有這樣的符號。 當然這並沒有增加 perl 的 regexp 功能, 只是讓使用者可以寫出比較簡潔的 regexp 而已。

再換一個例子請讀者自行練習: 從文件裡面抓出 ip。 也就是想抓 「看起來像是 host name」 的字串, 例如 163.17.9.5, penguin.im.cyut.edu.tw, mail.so-net.net, ... 等等。不妨就將本頁的原始碼存檔, 拿 regexp.shtml 當做資料檔來做實驗。 請參考以下提示, 逐步將你的 regexp 複雜化:

1. 先抓出連續出現的文數字或減號。
2. 後面再加上 「一個句點, 及一串連續出現的文數字或減號」。 因為 . 在 regexp 裡面有特殊意義 (「任何一個字元」), 所以這裡的 「一個句點」 前面必須加上倒斜線, 將它的特殊意義取消: \.
3. 其實第二步所加的東西可以重複出現 2 次, 3 次, ... (大概不會超過 9 次吧)。

參考答案在網頁原始碼某處 (沒有所謂的「正確答案」啦)。

最後看一個稍微複雜而完整, 很有成就感的例子: 網頁伺服器會將過去來訪本網站的每一人次摘要記錄在一個 access_log 檔裡面。假設我想統計每個小時 (0 點到 1 點, 1 點到 2 點, ... 23 點到 0 點) 的來訪人次, 產生 像這樣的圖。 需要撰寫複雜的 C/C++/Java 程式嗎? 先用 regexp 與一些簡單的命令: (每一步下完, 請用 less 看一下新產生的資料檔, 了解每一句話的意義, 並且看看是否與這裡的結果相同?))

perl -ne 'print "$1\n" if /:(\d\d):/' < access_log > ws_1.txt
sort < ws_1.txt > ws_2.txt
uniq -c < ws_2.txt > ws_3.txt
perl -ne 'print "$2 $1\n" if /\s*(\d+)\s+(\d+)/' < ws_3.txt > ws_4.txt

上面的 sort 指令, 顧名思義就是在排序; uniq -c 則將相鄰的重複列刪除, 並且計算重複的次數。 最後進入 gnuplot 下兩個指令

set data style lines
plot "ws_4TAB"

就完成了! 注意到在 gnuplot 裡面的 TAB 鍵一樣也有檔案名稱快打的功能。 如果你不怕長句的話, 上面四句其實可以改用 pipe 串在一起, 完全不需要產生中間的臨時檔。 滑鼠那麼好用, 為什麼許多真正的高手卻更喜歡用鍵盤? 比手畫腳那麼方便, 為什麼我們非英文科系的一般民眾也要要學英文? 非資訊科系不能學命令列嗎? 什麼樣的資訊教育才可以 組合活用, 才有長遠的投資價值? 筆者對此有一些看法, 完全不同於目前強調拉選單, 比炫麗的主流資訊教育思想。 (要求所有科目的老師用微軟公司的 power point 做教材, 就是資訊資訊融入教學? 呼! 哈!) 讀者在看完這個例子之後, 也許能夠產生一些共鳴。
貪婪: 需要的不多, 想要的太多

regexp 的搜尋引擎有一個特性, 叫做 greediness -- 能吃多少, 就盡量吃多少。 請再拿本頁的原始碼做實驗, 用 less 閱讀, 並搜尋 「一對雙引號之間的字串」: ".*" 用 perl 的第二種句型寫, 就是這樣: perl -ne 'print "$1\n" if /"(.*)"/' regexp.shtml | less 不妨在 less 裡面再搜尋一次, 令它反白。 注意到了嗎? 大部分 「一對雙引號之間的字串」 都被正確抓出; 但是有些地方卻因為一列上出現數個字串, 而令 regexp 抓過頭了。 例如 "text/css" 出現的那一列上面有三個字串, 結果 less 與 perl 從第一個引號開始, 到最後一個引號為止, 把其間所有東西都抓出來了。 這可不是因為 less 會抓出所有符合條件字串的關係 -- 果真如此, ' rel=' 和 ' href=' 就不應該反白才對。 這是因為 regexp 非常貪婪, 會在滿足搜尋條件的前提下, 盡情地吃到無法再吃為止。 但其實我們需要的並不多, 看到第二個雙引號, 老早就應該停下來了。 有時候, 貪婪還真是會誤事。 難怪 Linus Torvalds 要說: 「無論如何, 貪念永遠不是件好事」。

要解決這個問題, 可以用 [^...] "除了 ... 之外的任何一個字元"。 只要將 "任意字元重複出現任意次" 改成 "除了雙引號之外的任意字元重複出現任意次" 就可以了: perl -ne 'print "$1\n" if /"([^"]*)"/' regexp.shtml | less 請用錯誤 (貪婪) 的方式再試一次, 用力比較一下什麼地方不一樣。

在 perl 裡面, 還有一個更優雅的阻止貪婪搜尋的方法。 所謂貪婪搜尋的問題, 其實都出在 quantifier。 因為 quantifier 的出現, 才讓 regexp 搜尋引擎有機會選擇多吃一點或少吃一點。 任何一個 quantifier 後面只要加上問號, 就可以將這個 quantifier 轉化成不貪婪的 quantifier, 一旦吃足符合 regexp 的資料, 就盡早停下來, 不再多吃, 像這樣: "(.*?)"。 也許可以把這裡的問號翻譯成: 「我真的需要這麼多嗎?」

再舉一個例子。 /etc/passwd 這個檔案, 裡面存放使用者的個人資訊。 請用 less 閱覽, 並搜尋你的使用者代號。注意連續的兩個冒號, 這中間其實有一個存放 "真實姓名, 辦公室, 辦公室電話, 家中電話" 的欄位, 不過一開始都是空的。 請下 chfn 指令修改你的個人資訊。 (提示: 沒有人規定不可以填一點笑話進去; 當然你要先通過密碼檢查一關, 否則任何人都可以趁你離開電腦五分鐘時亂改你的資訊, 就不好玩了。) 下面這句話會產生 "使用者代號 = 真實姓名" 的對照表: perl -ne 'print "$1 = $2\n" if /^(.*?):.*:(.*?),/' /etc/passwd 請猜猜看以下搜尋條件分別會得到什麼結果? /:(.*),/ 及 /:(.*?),/ 及 /:[^:,]*,/ (當然, 現在只有一對括弧, 下命令的時候, print 後面就不應有 $2)

一個 quantifier 後面加了問號 (最常見的是 +? 與 *?) 並沒有改變它的意義, 改變的只是它的 「貪婪程度」。
全面代換字串

前面談的都是搜尋; 以下介紹如何運用 regexp 來對檔案內的特定字串做全面性的代換。 例如當朝陽技術學院升格成朝陽科技大學的時候, 需要將所有文件裡面的 cyit 改成 cyut; 其他地方原封不動。 如果只有 regexp.shtml 一個檔案要改, 可以這麼下: perl -pe 's/\bcyit\b/cyut/g' regexp.shtml > new.shtml (螢幕上看不到東西? 當然! 被我們用 output redirection 轉入檔案去嘍。 如果將上句中的 > new.shtml 換成 | less 就可以看到啦。) 然後用 diff 比較: diff regexp.shtml new.shtml | less 它會將兩個非常相似的檔案抓來比較, 只印出有差異的地方, 以 < 開頭的是左檔的內容; 以 > 開頭的則是右檔的內容。如果沒有問題, 最後再下 mv new.shtml regexp.shtml 覆蓋舊檔。

當然我不只一個檔案要改, 所以真正下的指令是: perl -i -pe 's/\bcyit\b/cyut/g' `find . -iname '*htm*'` 將本目錄底下所有檔名當中出現 htm 的檔案一口氣全部抓來修改。 不過這是危險動作, 初學者請勿模倣。有興趣的讀者請自行研讀 shell 講義 當中的命令結果代換, 並查手冊 man 1 perlrun 裡面有關 -i 的說明。即使是筆者也習慣用上一段的語法; 如果要一次改很多檔案, 也會先用安全的語法實驗, 找出最恰當的 regexp 寫法之後, 再改用這段的危險語法, 以免平白磨損硬碟。 此外, 先行備份以防萬一也非常重要。 水能載舟, 亦能覆舟; 學習運用原力的絕地武士們可要戒慎 (但是不要恐懼) 啊! 以下我們就用上段的安全語法來寫例子。

美國日期的寫法是 「月/日/年」 例如 "12/25/1999"; 而澳洲日期的寫法是 「日/月/年」 例如 "25/12/1999"。想將 report.txt 檔案中的美式日期全部改成澳洲式日期, 可以這樣下: perl -pe 's#\b(\d\d)/(\d\d)/(\d\d\d\d)\b#$2/$1/$3#' < report.txt

想要製作乾淨/有效/無障礙的 html 檔案, 最簡單的方式就是遵循 w3c 建議的 "Separation of Content from Presentation" 觀念 以 "強調" 為例, 在文件當中應避免使用 而要改用 更不應該在文件裡面放一大堆 (請不要說我對微軟有偏見 -- 它的 FrontPage 確實毒害了太多網頁設計者, 進而傷害了視障者及其他弱勢族群的瀏覽權益。請幫忙呼籲親朋好友, 叫大家發揮道德良知, 別再用 FrontPage 了!) 兩者其實都是斜體字, 但用 i 比較注重排版外觀; 用 em 表示重視的是文件結構) 以下這句把 test.html 檔案裡的 全部改成 同時把 全部改成 perl -pe 's#<(/?)i>#<$1em>#g' test.html 遇到 時, 這裡的 $1 就是空字串; 遇到 時, $1 就是 "/"
用命令產生一長串命令

把目前目錄下的所有 .shtml 檔更名為 .html 檔: find . -name '*.shtml' | perl -pe 's/^(.*)\.shtml$/mv $1.shtml $1.html/' 上面只是產生許多 mv 指令而已, 並沒有真正執行更名的動作。 如果確定沒錯, 可以把上面的結果 pipe 給 bash 去執行。

更改檔名這個例子示範了一個比代換字串更強大的技巧: 我們不僅可以把資料轉換成另一形式的資料, 還可以把資料轉換成程式! 以下列出幾個可以應用的場合, 請讀者自己試著寫出細節:

1. PostgreSQL 目前似乎無法批次匯入 (import) 大量資料, 如何將既有的純文字表格輸入 PostgreSQL? 可以把純文字表轉換成 psql 可以處理的 SQL 指令檔。
2. eznet 電話撥接程式 (真的很容易設定!) 可以管理很多 ppp 帳號。 如何把現有的帳號資料一次輸入 eznet?
3. gnuplot 可以畫複雜的函數圖形; 但是要畫大量的箭頭或文字就必須一句一句寫. 如何讓 gnuplot 把一個座標檔內的資料都以箭頭的形式畫出來呢?
4. 目錄 A (以及它的子目錄, 孫目錄 ...) 底下有許多文字檔; 目錄 B 有相同的目錄結構與檔案, 而檔案的內容也幾乎與目錄 A 下相應的檔案一模一樣. 如何用 diff 命令找出究竟有那幾個檔案不同?
5. 延伸上例, 假設讀者身為老師, 發覺學生 A 與學生 B 的期末作業 (許多 *.h, *.c 檔, 分別放在 A 與 B 兩目錄下) 用上題的方式檢查之後, 出奇地類似, 看起來只是部分變數名稱改變。 除了變數名稱的改變之外還有多少相異呢? 這裡要用 perl 產生的程式, 是內含呼叫 perl 命令的 shell script。

Perl 的 regexp 總整理

常用的 regexp 符號可以大致分為三類:

1. 比對 「一個字元」 的符號:
* [...] ... 當中任何一個字元
* [^...] 除了 ... 之外的任何一個字元
* . 任何一個字元
2. 具有 「定位」 功能, 但本身不吃掉任何字元的 anchor:
* ^... 以 ... 開頭的字串
* ...$ 以 ... 結尾的字串
* \b 文數字/非文數字 的邊界。
3. 計數用, 表達 「前面那個東西重複出現多少次」 的 quantifier:
* {5} 重複 5 次
* {3,7} 重複 3 到 7 次
* ? 可有可無 (0 次或 1 次)
* * 重複出現任意次, 包含 0 次
* + 重複出現任意次, 至少 1 次
所謂 「前面那個東西」 可能是一個字元, 也可能是由小括弧括起來的一長串

另外還有表達 「這一串」 的 (...), 及表達 「或」 的 |。

如先前所說, 支援 regexp 的程式很多。 以上所列的觀念, 在大多數支援 POSIX 標準的語言/軟體裡面都可以找得到。 但是不同的語言/軟體, 採用的符號可能有一點點細微的差別。 例如表達邊界, 在 perl 裡是 \b 但在 less 或 vi 裡卻是 \<...\> 又例如在 grep 當中, ? + | ( 等等符號要加上倒斜線才有特殊意義; 但在 perl 裡面, 這些字元反而是加了倒斜線就失去特殊意義, 變成比對到它本身。 讀者不必擔心記不得這麼多不同的規則 -- 筆者也記不太起來 :-) 瞭解觀念最重要; 至於細節, 需要用的時候再查手冊就好了。

我們之所以選擇 perl 來教 regexp, 有好幾個原因。 第一, perl 有一個很容易記的規則: 凡是標點符號, 加上倒斜線, 一定沒有特殊意義

第二, perl 替最常用的 [...] 定義了簡寫:

1. \d 其實就是 [0-9], "任何一個數字"
2. \D 其實就是 [^0-9], "任何一個非數字"
3. \w 其實就是 [a-zA-Z0-9_], "任何一個文數字"
4. \W 其實就是 [^a-zA-Z0-9_], "任何一個非文數字"
5. \s 其實就是 [ \t\n], "任何一個空白類字元"
6. \S 其實就是 [^ \t\n], "任何一個非空白類字元"

這裡有關 \w 與 \W 的說明並不嚴謹. 若要處理英文以外的西方語言, 請參考 perlre(1) 與 perllocale(1)。

第三, perl 的彈性很大, 小小的變化就可以造出三種不同的句型, 應付常用的搜尋/代換工作: (實際上簡單的變化還多得是; 不過筆者必須忍痛就此打住)

1. perl -ne 'print if /.../' 含有特定字串的那幾列, 全都印出來。
2. perl -ne 'print "$1\n" if /..(..)../' 不要前後文, 只印出特定字串就好。
3. perl -pe 's/.../.../g' 把文中所有特定字串全部代換掉。

其他支援 regexp 的工具

事實上如果用的是比較簡單的 REGEXP 來搜尋, 那麼 grep 'REGEXP' 的效果和 perl -ne 'print if /REGEXP/' (第一種句型) 的效果一樣。 所以簡單的搜尋 (只用到 [] . ^ $ * \b) 通常都用 grep 指令。 但是在 grep 中, 想使用 ? + () {} | 等功能, 必須要在前面加上 \ 例如搜尋 port 的範例, 如果用 grep 來做, 要寫成: grep -i '\bports\?\b' howto-index 所以比較複雜的搜尋, 用 egrep 或 perl 寫起來反而比較清楚。

同樣地, 簡單的字串代換可以用 sed 來做。 sed 's/REGEXP/SUBST/g' 的效果和 perl -pe 's/REGEXP/SUBST/g' 一樣。

高手們最喜歡常用的文字編輯器 vi 與 emacs 當然也都支援 regexp。

在 perl 紅起來之前, awk 曾經是最受系統管理人員歡迎的萬用瑞士刀。 事實上 perl 有很多語法都是從 awk (還有 C, 還有 shell script, ...) 學來的。

用 archie 尋找 ftp archives 時, 也可以使用 regular expression。 花的時間比較多, 但是或許可以避免遺珠之憾。

幾乎所有 scripting languages 都支援 regexp, 例如 perl, python, php, tcl, ruby, guile, ... 等等。

編譯語言 (例如 C, C++, ...) 的使用者可以取得 pcre 程式庫。 [7]
永遠的朋友 -- 文字檔

太空梭很棒; 但是大多數時候腳踏車比較實用。 我所有的資料 (程式, 文件, ...) 都盡量用文字檔儲存。 搭配 regexp, 在任何艱困的環境底下都能夠工作。
作業與更多範例

覺得內容太多, 一時無法吸收嗎? 沒有關係, 這些知識具有長遠的價值, 不會退流行, 所以也不急著立即完全吸收。 筆者花了很多年的時間, 每幾年學一點, 才將 regexp 學好 (例如 *? 與 +? 就是筆者開始教 regexp 很多年之後才學會的)。 另一方面, 在還沒有學完整之前, 就已經可以開始應用於日常作業當中了。 重點之一是: 要經常使用, 才會熟悉。 重點之二是: 不論是否用得出來, 至少要經常 認出可以使用 regexp 的場合。 如果您遇到一些實用的問題, 即使只是查覺到可能可以 (但不知如何) 用 regexp 解, 本文的目的也就達成一半了。 筆者懇請您將問題清楚描述, 如果確實可以用 regexp 解決, 我樂意為您服務; 如果您已自己解決問題, 更歡迎與我們分享。 因為這不僅解決您的問題, 同時也可以讓我收錄入範例/作業/考試當中, 讓其他讀者一併獲益!

1. 用 man 1 perlfunc 看手冊時, 想找 printf 函數的說明, 可以按 /printf 搜尋 printf, 並連續多按幾個 n (搜尋下一個)。 但是這樣做太慢 -- 因為用 printf 做例子的地方太多, 要按很多次 n 才會找到 printf 的定義。 怎樣找會比較快一點呢?
2. 有些文字檔後面會多出一些沒有用的空白字元。 請用 regexp 將它們刪除掉。
3. look 命令可以查字典 (沒有解釋, 只能知道如何拼字) 例如 look pr 會印出所有以 pr 開頭的英文單字。 想知道有一個英文單字 "特權" pr...ge 怎麼拼, 應該如何找比較快?
4. 在 linux 下要修改系統設定, 如果不熟悉眼前的視窗環境, 還是可以用下指令的方式來進行。問題是要下什麼指令才能修改滑鼠或網路的設定呢? 可以先下: ls /bin /sbin /usr/bin /usr/sbin/ | perl -ne 'print if /(cfg|cnf|conf|config)/' 得知系統內有那些看來像是改變設定用的指令, 再從裡面撿出與滑鼠或網路相關的指令來試。
5. (給朝陽的同學) 某個檔案裡面有系上同學的某些資料, 每列一筆, 其中包含學號。 (不妨用 last 指令的輸出做實驗) 請下指令抓出屬於你們班同學的部分 (單雙號有別, 不要抓到隔壁班的哦!)
6. Unix 底下的系統信箱放在 /var/spool/mail/ 目錄內。 請用 less 檢視檔案內容, 看看如何下指令抓出最近寄信給我的人。 如果你像我一樣用 mutt 或 elm 或 pine 等文字模式的軟體收發信件 (真的很方便, 速度快很多) 那麼讀過的信件一樣也以純文字格式儲存在家目錄底下 (例如 ~/mail/mbox) 。 如果你會 perl 語言, 還可以進一步寫一個短短的程式抓出 "過去六個月內至少曾經寄三封信給我的人"。 然後一個指令就可以寄信給這些人。 (也許你的 e-mail 改變了, 要通知眾親朋好友。)
7. /usr/X11R6/lib/X11/app-defaults/ 目錄下有許多設定檔, 裡面包含各種視窗前景背景顏色的設定等等, 長得像這樣: Rosegarden*background: #ffe4b5 這裡井字號開頭的三位數或六位數 16 進位數字代表顏色的 rgb 成分。 請抓出所有顏色 (不要前後文)
8. 在 DOS 下, 文字檔內的換列由 ^M ^J 兩個字元構成; Linux 下文字檔的換列只有 ^J 一個字元。 請下命令, 將來自 DOS 的文字檔每列最後面的 ^M (在 perl 裡面可以用八進位表示: \015 或用十六進位表示: \xd) 刪掉。當然也可以試著將來自 linux 的文字檔每列最後面加上 ^M, 變成方便 DOS 處理的文字檔。
9. 如果你把手冊的輸出存檔, 例如 man perl > perl.txt 再用 editor (例如 vi 或 pico) 去看, 會發覺檔案內有很多 ^H 也就是倒退字元。 這是因為過去的印表機都是靠 "倒退再印" 的方式來印底線或粗體字。 請下命令刪除這些字元。 (^H 用八進位表示: \010; 用 十六進位表示: \x8) 其實在 Linux 下其實可以直接用 man perl | col -b 解決這個問題, 不需要用 regexp。
10. 許多版本的 linux 以 rpm 管理套件。 下這個命令: rpm -qa --qf '%{NAME} <%{GROUP}> <%{SUMMARY}>\n' 可以查詢系統內有那些套件, 各別屬於那一類, 並印出摘要說明。不要理會複雜的命令, 我們有興趣的是它的結果:

mpg321
vnc
libxml
icewm
..。

請用 regexp 抓出第一對角括弧號裡面的東西 (例如 "Applications/Multimedia") 請分別試試看貪婪版, 「除...之外」版, 及不貪婪版的效果。
11. 請分析 last 的輸出, 統計週日至週六每天的登入人次 (不分那一週, 只要同是週二, 就全部算在一起) 並按照登入人次多寡對這七天排序。 提示: 把 perl 處理完的資料 pipe 給 uniq -c 與 sort -n 接續處理。

參考資料

1. http://penguin.im.cyut.edu.tw/~ckhung/l/mr/index.cgi?major=LDP
2. http://penguin.im.cyut.edu.tw/~ckhung/l/mr/index.cgi?major=METALAB&path=/docs/HOWTO/
3. http://penguin.im.cyut.edu.tw/~ckhung/l/mr/index.cgi?major=CPAN&path=/ports
4. http://www.cyut.edu.tw/~ckhung/a/c_90/cygwin.shtml
5. http://www.cyut.edu.tw/~ckhung/a/c_91.shtml
6. http://www.cyut.edu.tw/~ckhung/a/c013.shtml
7. http://www.pcre.org/
8. http://linuxtoday.com/news_story.php3?ltsn=1998-12-24-003-05-OP "Unix as an element of literacy" 及 http://www.osviews.com/modules.php?op=modload&name=News&file=article&sid=1084 "Death to the Wizards!" 兩篇有類似的看法.
9. 請參考其他文章:
中研院報告(1): http://phi.sinica.edu.tw/aspac/reports/94/94019/
中研院報告(2): http://phi.sinica.edu.tw/aspac/reports/96/96004/ (感謝 Y. Cheng 提供) < br /> http://info.sayya.org/~edt1023/vim/ (以 vim 為中心)
http://lib.stat.cmu.edu/scgn/v52/section1_7_0_1.html (英文)
http://www.ciser.cornell.edu/info/regex.html (英文)

雜七雜八還沒整理的舊資料

例如要找出所有「看起來像是 C 語言當中的 keyword 或 identifier 的字串」, 可以用 [A-Za-z_]\w* 又例如 perl 語言當中 split " " 的效果也幾乎可以用 split /\s+/ 來達成. 這些都只是簡寫, 並沒有增加新的功能, 但是可以讓我們寫起 regexp 來比較簡潔. 以下我們會經常使用; 但是請注意如果你用的是其他支援 regexp 的程式, 凡是用到這些簡寫的地方可能都要改寫。

1. []^-] 字元類別: 可以是 ] 或 ^ 或 - 當中任何一個字元。 要找的字元如果正好是有特殊意義的標點符號, 就把它放在它不可能有特殊意義的地方, 例如把 ] 放在最前面, ^ 不要放在最前面, - 放在最開始或最後面。 不過這樣寫不易讀, 建議只在 "用丟即棄" 的命令列當中使用。 如果出現在程式當中, 建議這樣寫: [\]\^\-] 日後維護才方便。
2. {2,4} 前一個樣版要出現 2 到 4 次. 延續上例, 例如要在 COPYING 檔案內找連續 2 個, 連續 3 個, 或連續 4 個數字, 可以在 less 內下: /\b[0-9]{2,4}\b 嚴格說來, 為了不遺漏掉 "19yy" 之類的字串, 應該這樣寫才完整: /([^0-9]|^)[0-9]{2,4}([^0-9]|$) 簡單地說, 我們本想要求「前後不可有數字」, 所以在 [0-9]{2,4} 之前與之後加上 [^0-9]; 但是 [^0] 的要求又太多了, 它要求 "要有一個不是數字的字元"; 那麼如果我們找到的一串數字正好出現在該列的最前面或最後面, 豈不是比對失敗了嗎? 所以我們再加上 "前面沒有東西了" 及 "後面沒有東西了" 這些可能狀況。
3. 想統計一下系統內所安裝的各類套件各有多少個: perl -ne 'print "$1\n" if /^Group\s*:\s*(.*\S)\s*Source RPM/;' rpm-listing 將結果 pipe 給 sort | uniq -c | sort -n | less 就可以看到由少而多的各類套件個數. 因為 regexp 引擎具有「貪婪」 (greed) 的特性 -- * 與 + 之類符號會盡其所能地吞噬它有能力吞噬的字串 -- 所以這裡需要有一個 \S 來阻止 .* 把 "Source RPM" 之前的空白吃進去. 如果沒有 \S 會怎麼樣? 在 less 當中做類似的搜尋就知道了 (但記得 \s 與 \S 只能在 perl 用)。
4. 列印出 myprog.c 所包含 (#include) 進來的所有標頭檔 (*.h) 檔名: perl -ne 'print "$1\n" if /^#\s*include\s<(.*)>/' myprog.c
5. 上節找六位或七位數字的例子, 我們可以用新語法重寫, 讓 perl 只印出 (每列上第一個) 找到的數字, 而不要整列印出來: perl -ne 'print "$2\n" if /(\D|^)(\d{6,7})(\D|$)/' Consultants-HOWTO
6. 印出所有看起來像是 URL 的字串: perl -ne 'print "$1\n" if m#(\w+://([-\w]+\.)*[-\w]+(:\d+)?[^<>\s"]*)#' ..。 這裡因為我們要找的字串當中有 "/", 和 perl 用來分隔搜尋字串 /.../ 的分隔字元衝突, 如果按照標準的寫法, 每個 / 都要變成 \/ 還好在 perl 內, 大部分的標點符號我們都可以拿來當做分隔字元. 本例用 # 當分隔字元, 那麼 / 就可以當做一般字元來比對而不需要加 \ 了。

1. 把一個程式檔當中的 (整數) x,y 座標顛倒過來: perl -pe 's/\[(-?\d)+,(-?\d)+\]/[$2,$1]/g' prog.pl 這個假設座標都是整數, 並以 "," 分開. (這裡假設我們要處理的是 perl, 且程式中的座標存在 anonymous array 當中)
2. 把 sample.c 內的 (大部分) /* ... */ 形式的註解改成 # ..。 形式的註解: perl -pe 's@/\*(.*)\*/@#$1@;' sample.c (也許我們想用 perl 重寫 sample.c 這個程式, 所以註解的形式當然要改嘍.) 不過跨列的註解還有層層相疊的註解就不方便用 regexp 改了。
3. 把 test 檔案內的文數字以外所有字元都給變成 %... 這種 url-escape 的形式: perl -pale 's#([\W])#"%" 。 sprintf("%02X",ord($1))#ge' test
4. sirobot 可以用來映射整個網站 (或其中一個子目錄), 但抓回來的檔案裡面, 許多 link 都會亂掉, 例如本來應該是 "abc.html" 的 link, 會變成 "..%2Fabc.html%2Fabc.html" 這裡的 "%2F" 其實就是 "/" 沒什麼問題; 但是 ".." 與重複出現的檔名就麻煩了。 以下命令可以一口氣修正本目錄下所有 htm(l) 檔: perl -i.bak -pe 's#%2F#/#g; s#\.\./(.+?)/\1#\1#g' `find . -name '*.*htm*'` 註: 有些比較複雜的狀況需要用這個更精確的寫法: perl -i.bak -pe 's#\.\.%2F(.*?\.\w+?)%2F\1#\1#g; s#"\.\.%2F(.*?)"#$1#g; s#%2F#/#g' `find . -name '*.*htm*'` 心得: 還是 wget 比較好用 ...

不論未來套裝程式如何進步, 提供功能如何多, 都不可能取代善用 regexp 的能力, 因為 regexp 不是一個功能或一個工具而已, 它的是一個表達力遠比選單視窗更豐富的人機介面。 學會這個豐富表達方式, 再理性地選擇真正有用的工具來配合使用, 讓你的新舊知識發揮相乘的效果, [6] 我想會比盲目地追隨流行更能夠有長遠的收穫. 另一方面, 讀者也應該體會到使用 .html 或 .txt 等文字檔儲存資料的好處。如果使用的是像 .doc 檔這樣封閉的二進位檔案格式, 就沒有許多好用的工具可以使用 (regexp 只是其中之一而已)。 [5]

筆者認為我們的「全民資訊教育」有必要全面檢討: 如果非得在傳統課程之外, 再給我們的中學生增加資訊科技的課程, 那麼真正應該教的不是 Office 2000, 而是 regexp。 [8] Regexp 之於電腦化文字處理的重要性, 不亞於四則運算之於數學的重要性. 基本的 regexp 並不比四則運算困難, 而它的應用範圍也不比四則運算小. 既然一般 (還沒有決定要念數學系的) 小學生可以學四則運算, 一般 (還沒有決定要念資訊相關科系的) 國中生當然也可以學 regexp. (不是因為 regep 本身那麼難, 需要國中生才能理解, 而是因為大部分應用的場合需要一些基本的電腦與英文知識.)

如果讀者從本文得到一點有用的知識, 也希望能夠做點什麼事情回饋社會, 那麼筆者建議把這篇文章印給你的上司/下屬, 老師/學生, 朋友看。 尤其可以拿給尚在求學的年輕朋友。一方面是因為他們沒有立即的就業壓力與沉重的歷史包袱, 比較可以接受目前非主流的知識; 另一方面是因為要期待正統的資訊教育擺脫廿世紀末的微軟包袱, 走上重視思考甚於重視操作的正途, 恐怕不是, 呃, 200\d 年的事。

From:http://www.cyut.edu.tw/~ckhung/b/gnu/regexp.shtml

定期備份

定期備份

主要是利用 tar 以及 find 來做特定目錄的備份。
tar:壓縮目錄成一個檔案
find:刪除特定條件的檔案

範例:
#!/usr/local/bin/bash
# This file will backup
#
# Http & MySQL
#
#=====================================================================
# History
# Make by denniswave 2004/04/19 first time!
#===========================================================================

# 建立備份的路徑!這樣的好處是可以清楚的知道每個檔案放置的地點!
basedir=/home/Ftp/backup
day=`date +%Y-%m-%d`
week=`date +%Y-%U`

# 1. MySQL ( PATH = /usr/local/mysql ) 每天備份
/usr/local/mysql/share/mysql/mysql.server stop
cd /usr/local
tar -zcf $basedir/mysql.$day.tar.gz mysql 2> /dev/null
/usr/local/mysql/share/mysql/mysql.server start

# 2. WWW及設定備份 每星期備份,每天更新
cd /usr/local
tar -zcf $basedir/www."$week".tar.gz www 2> /dev/null
tar -zcf $basedir/usr.local.etc."$week".tar.gz etc 2> /dev/null
cd /
tar -zcf $basedir/etc."$week".tar.gz etc 2> /dev/null
chmod 400 $basedir/*.*

echo "備份完成"

# 3. 刪除過舊的備份

echo "開始刪除舊檔案"
find $basedir/* -ctime +3 -exec rm -f {} \;
echo "舊檔案刪除完畢"

定期備份

定期備份

主要是利用 tar 以及 find 來做特定目錄的備份。
tar:壓縮目錄成一個檔案
find:刪除特定條件的檔案

範例:
#!/usr/local/bin/bash
# This file will backup
#
# Http & MySQL
#
#=====================================================================
# History
# Make by denniswave 2004/04/19 first time!
#===========================================================================

# 建立備份的路徑!這樣的好處是可以清楚的知道每個檔案放置的地點!
basedir=/home/Ftp/backup
day=`date +%Y-%m-%d`
week=`date +%Y-%U`

# 1. MySQL ( PATH = /usr/local/mysql ) 每天備份
/usr/local/mysql/share/mysql/mysql.server stop
cd /usr/local
tar -zcf $basedir/mysql.$day.tar.gz mysql 2> /dev/null
/usr/local/mysql/share/mysql/mysql.server start

# 2. WWW及設定備份 每星期備份,每天更新
cd /usr/local
tar -zcf $basedir/www."$week".tar.gz www 2> /dev/null
tar -zcf $basedir/usr.local.etc."$week".tar.gz etc 2> /dev/null
cd /
tar -zcf $basedir/etc."$week".tar.gz etc 2> /dev/null
chmod 400 $basedir/*.*

echo "備份完成"

# 3. 刪除過舊的備份

echo "開始刪除舊檔案"
find $basedir/* -ctime +3 -exec rm -f {} \;
echo "舊檔案刪除完畢"