正規表示法:表單資料驗證

     

「正規表示法」或「正規式」(Regular expressions)是在 UNIX 世界中發展出來的字串比對技巧,其基本概念是用一套簡單(但功能強大)的符號來比對字串,並可對符合比對條件的字串進行修改或其他運算。

Netscape 及 IE 在第四版後都支援 JavaScript 的正規表示法,特別適用於表單資料的驗證與修改。

JavaScript 的正規式是一個內建的物件,其建構函數(Construction functoin)為 RegExp,典型用法如下:

 

re = new RegExp("pattern", "flag")

上述用法也可以寫成:

 

re = /pattern/flag

其中,pattern 代表以正規表示法來顯示的字串,flag 則是比對的方式。flag 的值可能有三種,分別解釋如下:

舉例來說,我們的身份證字號的格式是由一個英文字母加上九個數字組合而成,如果我們要求使用者輸入身份證字號,就可以使用 JavaScript 的正規表示法來驗證其格式的正確性。例如,我們可用下列表單來要求使用者輸入身份證字號:

身份證字號:(第一個英文字母需大寫)

 

在上例中,我們利用 onBlur 事件來進行正規式的比對,換句話說,當使用者填完資料,要離開此欄位的時候,JavaScript 即會測知 onBlur 事件,並呼叫函數 checkID() 來對填入的資料進行驗證。

相關原始碼如下: 在上述原始碼中,/^[A-Z]\d{9}$/ 就是一個正規式,[A-Z] 代表由 A 至 Z 的所有可能英文字母,\d 代表由 0 至 9 的數目字(事實上也可以寫成 [0-9]),{9} 則代表需要有九個數目字,^ 代表字串開始位置,$ 代表字串結束位置,因此 /^[A-Z]\d{9}$/ 就代表可以比對身份證字號的正規式。formElement.value 代表使用者輸入的字串,re.test() 則會傳回 true 或 false,代表比對是否成功。若要不限定是大寫英文字母,只需將正規式改成 /^[a-zA-Z]\d{9}$/g 就可以了!(注意:若不加入 ^ 和 $,那麼 /[A-Z]\d{9}/ 就會比對到其他不合法的身份證字號,例如 AGF123456789 或是 F1234567890 等。因此,加入 ^ 和 $ 可保證比對正確的字串一定是由由一個大寫英文字母加上九個數字所構成。)

事實上,身份證字號本身就有內在的編碼規則,這些規則和使用者的性別有關,因此若要實現較完整的表單驗證,就必須應用較完整的身份證編碼規則

另一個簡單的例子,是要求使用者輸入信用卡號碼,這是一組16個數字的號碼,例如:

信用卡號碼:(格式:xxxx-xxxx-xxxx-xxxx)

 

當 onBlur 發生時,換句話說,JavaScript 會呼叫函數 checkCreditCard( ) 來對填入的資料進行驗證。相關原始碼如下: 在上例中,很顯然地,/^\d{4}-\d{4}-\d{4}-\d{4}$/ 就代表正確的信用卡格式。

 
正規式物件的方法功能
re.compile(pattern, flag)對正規式物件 re 進行編譯,以增加比對速度
re.exec(string) 或 re(string)比對正規式,並傳回陣列
re.test(string)比對正規式,並傳回比對結果(成功或失敗)

在上述範例中,我們只用到了正規式物件的 test() 方法來判斷比對是否成功,其他方法會在後序章節提到。

在進行表單資料驗證之前,我們應先進行表單資料修改,例如拿掉不必要的空格、英文字母大小寫轉換等,這些工作也可以由字串的 replace() 方法或正規式的 exec() 方法來達成,這是我們下一節的主題。

在下列的表格中,我們使用幾個簡單的範例來對正規式的應用做較完整的說明:

正規式說明及範例比對不成立之字串
/a/含字母 "a" 的字串,例如 "ab", "bac", "cba""xyz"
/a./含字母 "a" 以及其後任一個字元的字串,例如 "ab", "bac"(若要比對.,請使用 \.)"a", "ba"
/^xy/以 "xy" 開始的字串,例如 "xyz", "xyab"(若要比對 ^,請使用 \^)"axy", "bxy"
/xy$/以 "xy" 結尾的字串,例如 "axy", "abxy"以 "xy" 結尾的字串,例如 "axy", "abxy" (若要比對 $,請使用 \$)"xya", "xyb"
[13579]包含 "1" 或 "3" 或 "5" 或 "7" 或 "9" 的字串,例如:"a3b", "1xy""y2k"
[0-9]含數字之字串不含數字之字串
[a-z0-9]含數字或小寫字母之字串不含數字及小寫字母之字串
[a-zA-Z0-9]含數字或字母之字串不含數字及字母之字串
b[aeiou]t"bat", "bet", "bit", "bot", "but""bxt", "bzt"
[^0-9]不含數字之字串(若要比對 ^,請使用 \^)含數字之字串
[^aeiouAEIOU]不含母音之字串(若要比對 ^,請使用 \^)含母音之字串
[^\^]不含 "^" 之字串,例如 "xyz", "abc""xy^", "a^bc"

請注意在上表中,"^" 在兩條斜線中,代表一個字串的開始位置,因此 /^xy/ 代表以 "xy" 開始的字串。 同理,"$" 在兩條斜線中,代表一個字串的結束位置,因此 /xy$/ 代表以 "xy" 結束的字串。 但是如果將 "^" 放在兩個方括弧中,就代表「否定」,因此 [^aeiouAEIOU] 代表不含母音之字串。

另外,若要避掉特殊字元的特殊意義,就要在此字元前加上 "\",例如上表中的最後一列,"^" 在方括弧裡面是代表「否定」,因此若要在方括弧裡面比對 "^",就要使用 "\^",所以「不含 "^" 之字串」的通用式就是 "[^\^]"。

有些正規式會常被用到,因此已被定義為特定字元,以簡化整體通用式,這些字元可列表說明如下:

正規表示法的特定字元說明等效的正規表示法
\d數字[0-9]
\D非數字[^0-9]
\w數字、字母、底線[a-zA-Z0-9_]
\W非 \w[^a-zA-Z0-9_]
\s空白字元[ \r\t\n\f]
\S非空白字元[^ \r\t\n\f]

此外,我們可定義字元的重複次數,如下:

正規表示法說明
/a?/零或一個 a(若要比對? 字元,請使用 \?)
/a+/一或多個 a(若要比對+ 字元,請使用 \+)
/a*/零或多個 a(若要比對* 字元,請使用 \*)
/a{4}/四個 a
/a{5,10}/五至十個 a
/a{5,}/至少五個 a
/a{,3}/至多三個 a
/a.{5}b/a 和 b中間夾五個(非換行)字元

各位現在已經可以慢慢體會到正規表示式的威力了!利用同樣的方法,我們可以對各式各樣的表單輸入進行驗證,請參考下述範例。

注意事項

以 RegExp(pattern, flag) 的方式來建立正規式物件時,若 pattern 包含以反斜線開頭的特殊字元(例如 \d、\w、\s 等)時,我們必須再加上一個反斜線來保留其特殊意義。例如:
re = /\d+\s\w+/g
以 RegExp 為主的等效表示法為:
re = new RegExp("\\d+\\s\\w+", "g");