2011年11月30日 星期三

正規表示法(Regular Expressions)

正規表示法(Regular Expressions)

正規表示法並不是Perl所獨有的,但在Perl裡卻經常被拿來使用。

這也是為什麼很多人聽到Perl,直覺都會想到它的文字處理能力。

正規表示法。簡單來說就是比對樣式(pattern),

依照需求而去「尋找」我們所要的字串,並對這些字串加以處理。

比對符號是用等號波浪號(=~)來表示,

一樣我們直接從例子來看會比較清楚:

$string = "No pain, no gain.";# 給予一段字串 並存到變數裡

if ($string =~ /gain/)# 當$string裡面有gain時

{

print "match!";# 印出match訊息

}

else # 若否

{

print "sorry!";# 印出sorry訊息

}

執行一次結果就會是: match!


知道簡單的比對樣式(pattern)後,

來看看一些不一樣的用法吧!

有的時候我們需要找的東西不只一種,

比方說我要找美妝用品,但是只想看兩種品項的文章,

就可以把if內的條件寫成這樣:

if ($string =~ /(化妝水|面膜)/)# 當$string裡面有化妝水 或是(|符號)面膜

當然,也可以指定說,關鍵字一定都要符合的,

像是我只要某些牌子的手機:

if ($string =~ /Apple/ && $string =~ /phone/)# 當$string裡面有Apple 並且(&&符號)有phone

如此一來,找到的東西就只會同時有Apple以及phone。

值得一提的是,因為Perl正規表示法中,

樣式比對要考慮到大小寫、空格、換行、特殊字元等,

所以上面那行程式碼,萬一遇到apple的a是小寫時,

比對就會失敗,

要避免這個問題,我們可以使用一些「字符集合」

我們使用中括號([])表示 「或者」 的意思:

if ($string =~ /[aA]pple/ && $string =~ /[pP]hone/)# 首字大小寫都允許

如此一來,就可以避開首字大小寫的問題。


不過,如果每個字首都要定義大小寫,恐怕會寫成:

$string=~ /(/a|b|c|d|.......|z|A|B|C|D|......|_|)/

整串寫完真的會很壯觀呢!

當然,「字符集合」仍然有更方便的用法。

$string=~ /[a-zA-Z]/

短短這段字符集合就可以取代上面那段看起來很壯觀的程式碼,

表示大小寫都可以算比對成功。

$string=~ /[!@#$%^&*()_+=]/

而這樣就可以比對特殊字元!

但是問題來了,如果我要比對的是這個連字符號(-)呢?

上面的例子我們看到連字符號(-)已經被拿來當作取出a-z,A-Z的各個字符,

因此會使用到跳脫字元(escape character)

$string=~ /[\-]/

使用反斜線符號(\)表示下一個字元要跳脫(表示不做特殊用途)

因此就可以抓到連字符號。

而如果我們不要某些字,可以會使用插入符號(^)

$string=~ /[^A]/

表示我不要有A字元的樣式,以此類推。


知道使用字符集合增加樣式比對的複雜性後,

Perl的正規表示法其實也有特殊字元可以使用,

像是剛剛這段 $string =~ /[a-zA-Z]/

就可以簡寫成$string =~ /\w/

而常用的一些Perl正規表示法的特殊字元有:

\w:就等同於[a-zA-Z]的字符集合。

\W:就等同於[^a-zA-Z]的字符集合。 (大寫表示的意思)

\s:就等同於空白字元(space)。

\S:就等同於空白字元的字符集合。

\d:就等同於[0~9]的字符集合。

\D:就等同於[^0~9]的字符集合。

當然,你也可以這麼使用,

假設我想比對的樣式,長度在5~10之間,

那麼一樣可以使用修飾字元,

使用的方式就是使用大擴號({})來表示:

$string =~ /\w{5,10}/

如此一來就可以抓到長度5到10的英文字。


再來我們要回來看看正規表示法的修飾字元

一樣我們用例子來說明,

如果我想抓取一段句子中,perl這個字串,

那麼你會遇到一個問題,除了首字大寫(Perl)之外,

句子中可能會有全部小寫(perl),以及全部大寫(PERL)的情況,

那麼表示起來可能又會寫一大段,

這時候修飾字元就派上用場了:

$string=~ /perl/i

注意到了嗎?樣式比對後面加了一個 i 表示 ignore (忽略)

表示我要忽略大小寫,如此一來上面的問題就可簡單處理掉了!

其他修飾字元還有:

$string=~ /perl/s

樣式比對後面加了一個 s 表示我要進行跨行(跨越\n)做比對

$string=~ /perl/g

樣式比對後面加了一個 g 表示我要對樣式進行全面比對(Match globally)

$string=~ /perl/o

樣式比對後面加了一個 o 表示我只要比對一次(Match once)

當然,你也可以把這些修飾字元都一起使用:

$string=~ /perl/io

樣式比對後面加了一個 i 以及 o

表示我想要進行忽略大小寫的樣式比對,並且只要成功比對一次就好。


知道如何比對樣式後,有時我們也會需要取得比對結果,

在Perl的正規表示法裡,有預設變數來讓你取得比對的結果,

預設的變數是使用$1來接比對後的結果,

然而,如果還有其他比對結果,則會用到$2,

如果還有就會持續遞增:像是$1, $2, $3 ...

而要把我們想要取得的樣式存到這些變數裡,

方法也很簡單,就是用小括號()把這些樣式包起來。

一樣我們從例子來說明:

$string = "God helps those who help themselves.";# 給予一段字串 並存到變數裡

if ($string =~ /(God)(.*)(those)/i)# 當$string裡面有(God)以及(任何字元)還有(those)時

# 因為修飾字元有i 所以會忽略大小寫 並且 因為有三個小括號

# 所以成功比對的樣式會依序存入3個預設變數 即是 $1 $2 $3

{

print "$1 \n";# 印出$1以及換行

print "$2 \n";# 印出$2以及換行

print "$3 \n";# 印出$3以及換行

}

執行結果就會看到,

這些比對的樣式依序被抓取出來。

$1裡面存的就會是"God"

$2裡面存的就會是" helps " (空格也會被抓進來)

$3裡面存的就會是"those"


接下來我們來看看更精確的描述正規表示式,

我們會使用到的是定位點

透過定位點,可以表示我要找的樣式是在開頭,或是在結尾。

$string=~ /^perl/

插入符號(^)在這裡表示以這個樣式「開頭」

需要注意的是,在這裡所使用的插入符號(^)跟「字符集合」意思不同

一個表示「開頭」,一個表示「非」,可別搞混了!

$string=~ /perl$/

錢字符號($)在這裡表示以這個樣式「結尾」


再來是正規表示法的比對與替換

如果我們要把比對好的結果作替換,

寫法稍微有點不同,格式會長得像這樣:

$string=~ s/原本的樣式/替換的樣式/

利用三個反斜線夾住要比對以及替換的樣式,

並且在前面加上一個 s 表示 substitute (替換)。

後面一樣可以加上一些修飾字元,像是上面提到的忽略大小寫(i)等等。

我們直接看例子:

$string = "我不喜歡吃苦瓜,我還是不喜歡吃苦瓜。";# 給予一段字串 並存到變數裡

$string =~ s/苦瓜/鹹蛋/gi; # 把苦瓜替換成鹹蛋 全部都換(g)並忽略大小寫(i)

print "$string";# 印出$string

執行結果可以看到所有的苦瓜,都被換成了鹹蛋!


最後是正規表示所用到的萬用字元(.)問題,

Perl的正規表示是貪多比對

即是Perl預設會去找到符合需求的「最大集合」。

用例子看會比較清楚:

$string = "我不喜歡吃苦瓜,我還是不喜歡吃苦瓜,我真的不喜歡吃苦瓜。";

if ($string =~ /我不喜歡(.*)苦瓜/)# 取得夾在 我不喜歡 以及 苦瓜 之中的樣式

{

print "$1 \n";# 印出$1以及換行

}

執行以後會發現,

我們原本希望只抓到"吃",這一個字,

但Perl的預設就是找到「最大集合」,

這就是所謂的貪多比對

如果要避開這個問題,我們會在比對的量詞後面,加上問號(?)來表示不貪多

因此我們把上面的式子改寫成為:

$string = "我不喜歡吃苦瓜,我還是不喜歡吃苦瓜,我真的不喜歡吃苦瓜。";

if ($string =~ /我不喜歡(.*?)苦瓜/)# 用問號表示不貪多比對

{

print "$1 \n";# 印出$1以及換行

}

如此一來,執行結果就會符合我們的期待


正規表示式就到這邊結束,接下來要回到控制敘述的迴圈操作

2011年11月8日 星期二

副常式(Subroutine)

副常式(Subroutine)

副常式。很多時候我們常為了處理類似的工作時,重複寫些相同的程式碼,

這個時候,我們就必須藉由副常式(Subroutine)來保存一個可以重複使用的區塊,

以便未來遇到同樣的問題時,可以不用再重新寫一次相似的程式碼。

在Perl中,我們使用sub表示我要宣告一個副常式,

之後再賦予這個副常式的名字,如:sub name {......}

寫好副常式後,使用的方式也很簡單,我們用and符號(&)表示我要使用副常式。

一樣我們直接看例子:

sub squre # 宣告一個副常式 叫做squre

{

$number = $number**2; # 把原本的變數平方後 取代原本的$number

print $number; # 印出最後的$number

}

$number = 4; # 設$number為4

&squre; # 執行名為squre的副常式

來解釋一下上面的程式碼。程式在跑的時候都是由上往下,

第一行的sub,把要做的事情都包起來了,

因為沒有and符號(&),所以程式不會去執行sub裡面的運算,

一直到$number = 4;這行

程式才開始設定一個變數為4,而再下一行

&squre;

程式看到and符號(&),表示要執行名為squre的副常式,

才會回過頭去執行副常式內的運算,

在這裡,因為我們已經宣告了變數,才去執行副常式內的運算,

所以不會出現變數尚未定義的問題。

因此,最後的執行結果會為 16


知道如何簡易的定義以及使用副常式以後,

接下來我們來講副常式中,參數的傳遞。

直接從例子看會比較清楚:

sub hello # 宣告一個副常式 叫做hello

{

print "hello, @_"; # 印出hello以及傳進來的參數

}

$name = "阿逸"; # 設$name為阿逸

&hello($name); # 執行名為hello的副常式 並且傳遞參數$name進去

一樣我們來解釋這段程式碼,

因為我們在執行副常式的時候,把一個參數傳進去(變數$name),

因此在副常式中會有一個預設的陣列(@_)來接這個參數,

既然預設是陣列,也就代表可以丟不只一個參數,

所以如果寫成:

sub hello # 宣告一個副常式 叫做hello

{

print "hello, @_\n"; # 印出hello以及全部傳進來的參數 換行

print "hello, $_[0] $_[1]\n"; # 當成陣列[元素]來處理也可以

}

$name1 = "阿逸"; # 設$name1為阿逸

$name2 = "阿信"; # 設$name2為阿信

&hello($name1, $name2); # 執行名為hello的副常式 並且傳遞參數$name1及$name2進去

這麼做也是可以執行的。


知道如何傳遞參數給副常式後,

大多數情況下,除了參數,我們也希望能夠從副常式中,

取得經過運算後的結果,也就是副常式的回傳值。

這時候我們會用到的保留字就是return

表示我要把某一個值帶出副常式(也就是回傳出去),

一樣我們用例子來解釋:

sub squre # 宣告一個副常式 叫做squre

{

$number_sub = $_[0]**2; # 把傳進來的參數$number取平方 取代$number_sub

return $number_sub; # 把$number_sub這個值 傳出去

}

$number = 4; # 設$number為4

$squre_number = &squre($number); # 執行副常式並且傳遞參數進去

# 再用$squre_number接副常式的回傳值

print $squre_number; # 印出$squre_number

執行結果就會是 16


以上就是簡單的副常式傳遞參數、回傳值的使用,

當程式越寫越複雜的時候,將很多類似的功能都寫成副常式,

可以大量減少重複coding類似程式碼的時間,

不過一旦你的副常式大量被重複使用時,要記得考慮參數傳遞、傳出的順序問題,

避免其他使用相同副常式的程式,因為傳遞順序更動而造成運算錯誤,

在這裡就不討論到這部分啦!

接下來,就要講Perl最大的利器之一,

Perl的正規表示式(Regular Expressions)。

2011年11月5日 星期六

專為PTT使用者所打造的 - PCMAN + BBI

不知道各位有沒有遇過這樣的狀況?

有時候我們在PTT(台大BBS站)上,

看到很棒的文章,想要分享給朋友們,

但常常因為對方不會使用PTT而無法分享。

而這款 PCMAN + BBI 的小軟體,

增加了不少方便的功能,馬上來看看吧!


軟體名稱: PCMAN + BBI

軟體網址: http://bbi.com.tw/bbs-download.html

軟體功能

1. 保留原有的PCMAN功能

2. 自動登入PTT帳號

3. 分享PTT文章至Facebook、plurk、Google+

4. 製作PTT網址

5. 每日精選文章

6. 熱門看板連結

7. 搜尋PTT熱門看板文章

馬上就來看看有什麼不同吧!


目前可以下載的版本有,正式版跟免安裝版,

阿逸這篇是以正式版來跟大家分享。

安裝好的PCMAN+BBI 一開啟後,會顯示BBI開頭畫面,

可以看到各大熱門看板當紅的文章,都可以用滑鼠操作

不過,因為還沒有登入的關係,會要求你先輸入帳號密碼,

輸入完後,會自動幫你連結到,你所點選的那篇文章中,

而操作方式跟以往在PCMAN下操作完全相同。


當你看到喜歡的文章,想要分享給其他人觀看的話,

進入該篇文章後,按下右上角的「存」字圖案,

便會開始儲存文章,

儲存完後,會出現網頁版的畫面,

此時你可以注意到,多了幾個按鈕,

分別是Facebook的like鍵、噗浪的圖型按鈕、以及Google+的+1鍵。

點選Facebook的like鍵後,文章會被分享在Facebook中,

不會使用BBS的人,也可以透過滑鼠瀏覽你分享的文章!

真的很方便呢!

而另一項「製作PTT網址」,則僅適用於有安裝PCMAN+BBI的使用者

所以在這邊就不細談了,

有興趣操作的人,歡迎到開發者的網站,

參考這篇:產生PTT網址教學


2011年11月3日 星期四

逃離推銷的好幫手! - 來電救救我 (iPhone)

不知道各位有沒有被推銷人員纏上的經驗?

阿逸自己很不喜歡走在路上就一直被纏著填寫問券,

如果各位也是,那這款APP絕對不能錯過!


來介紹這款APP吧!

這是一支可以製造假來電的手機程式 - 來電救救我

在你被推銷員纏上的時候,可以順利逃離現場!

因為是中文介面,相信各位可以輕鬆上手!

開啟程式時,點選「來電救救我」的按鈕就可以進入設定畫面。

接著,這就是這程式有趣的地方,你可以自由輸入假來電的解救者人名、電話

如果想逃離的場合都是熟人,那也沒關係,點選解救者旁邊資料夾,可以開啟通訊錄,

程式自動會幫你把通訊錄的電話號碼跟人名抓出來。

更好玩的是,注意到號碼旁邊的小框框了嗎!

沒錯!可以從手機圖庫裡選一張照片,當作來電大頭貼!

設定好後,就可以開始設定多久後要拯救你啦!

五、四、三、二、一。 時間到!

哇嗚!還真的是有模有樣呢!

(以上圖片取自:一克拉的夢想 設計師 阿信)

按下「接聽」後,也還真的可以聽到語音呢!

不過當然,畢竟這是應用程式,別忘了把應用程式的聲音調大喔!

不然就不像是對話的感覺了!

如果你不喜歡內建的語音,當然也有提供自行錄製的功能,

請解救者本人幫你錄製一段,就更逼真啦!

美中不足的是,無法自訂來電鈴聲,期望之後的改版可以增加!

當推銷人員出現在不遠處時,或是處在尷尬的場合,

知道該怎麼裝忙了吧!哈哈!