2007年12月2日 星期日

正規表達式


來源:
何謂正規表達式



PHP繼承*NIX的一貫傳統,完全支援正規表達式的處理,對於用過PERL的正規表達式的人大都會理解它的功能非常強大,可是對於初學者來說確實不是件容易的事。

例如,如果有一個使用者輸入的字串,如「Z123456789」,想驗證使用者輸入的第一個字元是否是英文字母,而且都要大寫,這該如可判斷?

這時候,可能解決的方法是先「取得第一個字元」,再利用「A ~ Z」ASCII值的範圍來判別這個字元,所以您可能會將程式寫為:

01:
02:
03:
04:
05:
06:
07:
08:
09:
10:
= 65 AND ord($b) <= 95 ) {     echo  "驗證合格!";  }  else {     echo  "第一個字元不是大寫字母!";  } ?>

ch6-2-1.php

執行結果>>

第03行:取得第一個字元;
第05行:研判第一個字元是不是在A(ASCII值是65)到Z(95)之間,若是,那第一個字母就是大寫字元。

此時,換一個比較複雜的狀況,也就是要驗證使用者輸入的E-mail地址是否合於標準格式,例如 abc@mail.tceb.edu.tw,那要如何檢查呢?

有人就發展出一套「字串樣式比對的技述性語言」,用來:

  • 檢查某字串是否完整對應到某樣式 (核對)
       ─ 例如某字串是否符合E-mail「帳號@網域名稱」的格式
  • 在某字串中找尋對應樣式的子字串 (搜尋)
       ─ 例如在一篇文章中找出有關「大雄」二字的字串部份
  • 由字串中取出對應到某樣式的字串 (取代)
       ─ 例如將文章中有關「大雄」二字的字串取代為「哆啦A夢」四字的字串。

簡單的來說,就是利用「正規表達式」來進行字串的比對及處理,但由於它的功能強大,相對也比較複雜,以下僅就較常用到的「語法規則」來解說:

一、行的開頭或結尾(Start and End of the Line)

符號
說明
^
會比對匹配文章裡的每一行開頭
$
會比對匹配文章裡的每一行結尾

例如:

 狀況一:如果寫成 「 ^This 」,則字串:「This is a book」符合這規則; 「Is this the book」就不符合這規則。

 狀況二:如果寫成 「 book$」,則字串:「This is a book」、「Is this the book」都符合這規則。

 狀況三:如果寫成 「 ^book$」,則只有字串僅能有 「 book 」這個單字,前後都不可以有其他文字出現。

 狀況四:如果寫成 「 this」,則字串中任何位置只要有「this」這個單字,都符合規則;但大小寫有區別,例如「This is a book」不符合這規則,而「Is this the book」符合這規則。

二、字元集合(Character Classes)

符號
說明
[集合]
比對字元集合(範圍)的「一個」字元。

例如:

 狀況一:如果寫成「 H[123456] 」,則表示字串可以是「 H1、H2、H3、H4、H5、H6 」都符合這個規則。

 狀況二:如果寫成「 H[1-6] 」,則表示字串可以是「 H1、H2、H3、H4、H5、H6 」都符合這個規則,也就是可以將「 [123456] 」簡寫為「 [1- 6] 」。所以,有關英文字母、數字及一些標點符號可表示如下:

[a-z] 比對所有的小寫字母
[A-Z] 比對所有的大寫字母
[a-zA-Z] 比對所有的字母
[0-9] 比對所有的數字
[0-9.-] 比對所有的數字,句號和減號
[ \f\r\t\n] 比對所有的空白字元(注意 \t 前面是一個「空白」字元)

所有之前的「Z123456789」的例子可以改寫如下:

01:
02:
03:
04:
05:
06:
07:
08:
09:
ereg ("^[A-Z]",  $a ) ) {
echo "驗證合格!";
} else {
echo "第一個字元不是大寫字母!";
}
?>

ch6-2-2.php

執行結果>>

第04行:利用ereg函數來比對第一個字元是不是大寫字元;^ [A-Z] 都是可以組合的規則。

三、「非」或「排除」字元集合

這個部份前二項「 ^ 」與「 [ ] 」規則的組合,但「放的位置不同」,其表達的意義也不同,所以特別說明如下:

  狀況一:如果寫成「 ^[A-Z] 」,則表示字串開頭的字元是英文大寫字母成即符合規則,例如「Z123456789」。

 狀況二:如果寫成「 [^A-Z] 」(注意 ^ 的位置),則表示字串開頭的字元「不可以」是英文大寫字母,例如「Z123456789」就不行,但是如果是「 z123456789」(小寫) 或 「123456789Z」(開頭是數字)都符合這規則。

四、比對任意字元「.」 ( Dot,點)

直接用範例來說明:

 狀況一:如果寫成「 A[.]B 」,則表示字串應是「 A.B 」才符合規則。(與前面介紹的規則相同)

 狀況二:如果寫成「 A.B 」,則表示字串寫成「 A1B 」、「 AzB 」、「 A+B 」、.... 都符合規則,也就是第 2 個字元是任意的。

五、範圍比對,利用「 { } 」(大括號)

這個符號是用來比對「重複出現」的字元數,語法是「 {最小值, 最大值 } 」,利用範例如解說:

範例 說明
^a$ 比對 a
^a{2}$ 比對 aa
^a{2, 4}$ 比對 aa 或 aaa 或 aaaa (只要是其中一種都符合規則)
^a{2,}$ 比對至少有 aa 開頭的字串就行,也就是 aaa、aaaa、aaxxx 都符合(注意! 「 ,} 」之間不可有空白」
.{2} 比對所有雙字元,例如aa、bb、11、&&都可

六、特殊字元「? 」、「*」、「+」

這三個符號其實是上面規則定義的延伸,說明如下:

符號
說明
?
等於 {0,1},表示「前面的字元可以不出現(0)或出現一次(1)」
*
等於 {0,},表示「前面的字元可以不出現(0)或多次出現」
+
等於 {1,},表示「前面的字元必須出現一次(1)以上 」

七、其他:「|」符號及「 ( ) 」括號

符號
說明
相當於「OR」的意義;例如 「 A(B|b)C 」表示「ABC」或「AbC」都符合規則。
( )
指定字元序列,簡單來說,就是一個字串,例如 ^(book|notebook)表示開頭文字字串只要是 book 或 notebook 都符合規則。

所以,要比對 e-mail 格式的話,例如 abc@mail.tceb.edu.tw,那正規表達式的規則可以寫為:

也可以寫成「 ^(.+)@(.+)\.(.+)\.(.+)\.(.+)$ 」,這種「天書」剛開始學會很辛苦,可是一旦學會之後,您會發現往後在處理一些「驗證」字串功能時,就能理解其功能的強大。




正規表達式的函式




在瞭解何謂正規表達式及知道它的規則後,接著就是要將它應用到PHP程式設計中了。

在PHP處理正規表達式的函數大致可分為三類:

  • 搜尋與比對 ─ ereg( ) 或 eregi ( )
  • 搜尋並取代 ─ ereg_replace( ) 或 eregi_replace( )
  • 字串分割 ─ split( ) 或 spliti( )
ereg eregi 搜尋與比對
語法
ereg ( string pattern, string string [, array regs])
說明

本函式以 pattern 的規則(正規表達式)來搜尋與比對字串 string。
比對結果傳回的值放在陣列參數 regs 之中:

  • regs[0] 內容就是原字串 string
  • regs[1] 為第一個合乎規則的字串
  • regs[2] 就是第二個合乎規則的字串,餘類推。

若省略參數 regs,則只是單純地比對,找到則傳回值為 true

ereg( )與 eregi( ) 功能類似,語法相同,唯ereg( ) 在比對字串時有大小寫之分,eregi( )則大小寫無關。

傳回值
int (整數)
範例
01:
02:
03:
04:
05:
06:
07:
08:
09:
10:
11:
12:
13:
14:
 $regs[0]
";
echo "陣列 1 => $regs[1]
";
echo "陣列 2 => $regs[2]
";
echo "陣列 3 => $regs[3]
";
} else {
echo "錯誤日期格式: $now";
}

?>

ch6-2-3.php

執行結果>>

第05行:比對格式是否符合 "YYYY-mm-dd 格式。


ereg_replace eregi_replace 搜尋並取代
語法
ereg_replace ( string pattern, string replacement, string string)
ereg_replace ( 比對的規則, 取代的字串, 比對的字串)
說明

本函式以 pattern 的規則(正規表達式)來搜尋與比對字串 string,並將符合規則的比對字串取代掉,再傳回取代後的結果字串

ereg_replace( )與 eregi_replace( ) 功能類似,語法相同,唯ereg_replace( ) 在比對字串時有大小寫之分,eregi_replace( )則大小寫無關。

傳回值
string (字串)
範例
01:
02:
03:
04:
05:
 $change";
?>

ch6-2-4.php

執行結果>>



split spliti 字串分割
語法
split ( string pattern, string string [, int limit])

split ( 比對的規則, 比對的字串 [,處理的筆數])
說明

本函式可將字串依指定的規則分開。切開後的傳回值為陣列變數。參數 pattern 為指定的規則字串、參數 string 則為待處理的字串、參數 limit 可省略。

如果參數 limit 不省略,則表示處理的數量,換言之,最多產生的陣列數。

split( )與 spliti( ) 功能類似,語法相同,唯split( ) 在比對字串時有大小寫之分。

傳回值
array (陣列)
範例
01:
02:
03:
04:
05:
06:
07:
08:
09:
10:
11:
";
var_dump($r1);
echo "
";
var_dump($r2);

?>

ch6-2-5.php

執行結果>>

第03行:用「- 」做為規則分割;
第04行:指定處理數為2。

結果:
123-456-789-abc
array(4) { [0]=> string(3) "123" [1]=> string(3) "456" [2]=> string(3) "789" [3]=> string(3) "abc" }
array(2) { [0]=> string(3) "123" [1]=> string(11) "456-789-abc" }

【下列文章您可能也有興趣】

沒有留言: