Regular Expression - 正規表示式
正規語法 (Regular Grammar) 是一種相當簡單的語法,這種語法被 Perl 語言成功的用於字串比對,接著成為重要的程式設計工具。此種標準的正規語法後來被稱為正則表達式 (Regular Expression)。目前,大部分的語言都已納入正則表達式的函式庫,正則表達是可以說是程式設計師必定要瞭解的工具,也就是常識的一部分。
先看個簡單的例子
//RegExp是 Regular Expression的縮寫
//這句正規表示式要求輸入的資料只能是0~9的其中一個字元
var pattern = new RegExp("^[0-9]$");
console.log( pattern.test("0") ); //true
console.log( pattern.test("a") ); //false
console.log( pattern.test("12") ); //false
先不用了解程式碼的細節,稍微對正規表示式有個簡單的概念就好,我們進一步了解這奇奇怪怪的正規表示式到底該怎麼制定。
定義規則算式
規則算式常值是(regular expression literals)由一連串寫在兩個斜線字元(/)之間的字元所組成,譬如:/javascript/,夾在兩個斜線中間的部分,我們稱為pattern。把規則算式常值指定給變數後,該變數就成為一個規則算式物件。譬如:
var regexp = /[jJ]avaScript/;
有時候會在/pattern/後加上另一個符號,我們稱作attributes(修飾符),組起來就變成/pattern/attributes,譬如:
var regexp = /[0-9]/g;
以下是attributes的參考資料,先不用認真看,等等要用到再回頭查就好
修飾符(attributes) | 描述 |
---|---|
i | 執行對大小寫不敏感的匹配。 |
g | 執行全局匹配(查找所有匹配而非在找到第一個匹配後停止)。 |
m | 執行多行匹配。 |
到這邊大家應該還是很模糊吧!沒關係,我們實際做一些簡單的練習,
驗證手機號碼
手機號碼是09開頭,後面接8個數字,不多不少,像是0912345678
,所以想要驗證一筆資料是不是手機號碼,所要撰寫的程式碼如下:
var pattern = /^09[0-9]{8}$/;
var str = "0912345678";
var result = str.match(pattern);
console.log(result);
//輸出結果:[ "0912345678" , index: 0, input: "0912345678" ]
// ↑符合規定的字串 ↑原本的字串
第一步要撰寫正規表示式,我們用到的符號如下
形式 | 代表的字元集合 |
---|---|
^ | 定於字串首的錨點。在多行模式下,則是定於行首的錨點。 |
$ | 定於字串尾的錨點。在多行模式下,則是定於行尾的錨點。 |
[...] | 方括號中列出之字元的集合。我們可以用「首字元-尾字元」的簡寫式來定義一段連續字元,譬如:[A-Z] 是 26 個大寫英文字母的集合、[0-9] 是 10 個阿拉伯數字的集合。 |
{n} | 前一項正好重複 n 次 |
說明/^09[0-9]{8}$/
的由來:
- 09是固定的,所以我們直接打上去
/09/
- 後面的要接的是0~9隨意一個數字,所以我們要打
[0-9]
,[]
只代表一個字元,如果寫[0-9a-zA-Z]
則代表這個字元可以是數字或字母,變成/09[0-9]/
- 但這只代表一個字元,要重複8次才行,所以緊接著加上
{8}
,會變成/09[0-9]{8}/
- 頭要加上
^
,尾巴則加上$
,/^09[0-9]{8}$/
寫好正規表示式後,開始比對,使用match函式,match函式是會回傳符合正規表示式的字串,沒有符合的話會回傳null
,符合的話則回傳一個物件,格式如上面程式碼註解所寫的樣子。
還有哪些函式可以用:
- String型態中可使用正規表示式的函式
練習
如何比對手機號碼的程式我們已經寫好了,可以驗證的格式如0912345678
,但如果想要驗證的格式是0912-345-678
,那正規表示式又該怎麼寫呢?這次練習,我們用\d
來取代[0-9]
。
還有很多的符號要學,可以參考教學網站
一次只指定一個字元不過癮,也可以用Greedy quantifiers來指定字元可能出現的次數:
形式 | 意義 |
---|---|
X? | X出現一次或完全沒有 |
X* | X出現零次或多次 |
X+ | X出現一次或多次 |
X{n} | X出現n次 |
X{n,} | X出現至少n次 |
X{n,m} | X出現至少n次,但不超過m次 |
一些常用的範圍,我們可以使用預先定義的字元類別:
形式 | 意義 |
---|---|
. | 符合任一字元 |
\d | 等於 [0-9] 數字 |
\D | 等於 [^0-9] 非數字 |
\s | 等於 [ \t\n\x0B\f\r] 空白字元 |
\S | 等於 [^ \t\n\x0B\f\r] 非空白字元 |
\w | 等於 [a-zA-Z_0-9] 數字或是英文字 |
\W | 等於 [^a-zA-Z_0-9] 非數字與英文字 |
選擇、群組、與參照(因為 | 會有問題,所以以下表格 | 用 l 代替)
形式 | 意義 |
---|---|
xly | x和y中,兩者擇其一,如 /aalbb/ 表示 aa 或 bb |
(...) | 把括號中的項目視為一個單元,同時把符合括號內規則的子字串存在參照(reference)中。 |
\n | n是一個 1 到 99 的整數。用來表示第n個參照,其中存放符合第n個群組的子字串(第n個左括號所建立的群組) |
滿滿的範例,看著看著就學會正規表示式了
規則算式 | 相符的字串 |
---|---|
/a{1,3}/ | a, aa, aaa, aaaa, baab |
/ab{3,}/ | abbb, abbbb, babbba, abbbbbbbbb |
/[_A-Za-z]\w*/ | JavaScript 合法的識別字名稱 |
/[A-VXYa-vxy]\d{9}/ | 身份證字號:英文字母(W 和 Z 除外)後跟 9 個阿拉伯數字 |
/\d+/ | 不帶正負號的整數,如:8, 26, 123, 7823 等等 |
/[+-]?\d+/ | 帶或不帶正負號的整數,如:8, +26, -123, 7823 等等 |
/[+-]?\d*.?\d*/ | 帶或不帶正負號的整數或小數,如:8, -15, +26.3, -123.0, 78.23 等等。註:由於 . 是一個特殊字元,所以在左邊的式中必須在其前加反斜線。 |
規則算式 | 相符的字串 |
---|---|
/ab l cd l ef/ | ab, cd, 或 ef |
/0(2 l 4)\d{8}/ | 台北或台中地區的電話號碼,如: 0212345678 或 0426328001 |
/(\d+).\1/ | 小數點前後數字相同的字串,如:1.1, 123.123, 或 011.011 |
/(\d+)([a-z]+)\2\1/ | 12abab12, 34aa34 |
/(\d+([a-z]+))\2\1/ | 12abab12ab, 34aa34a |
/(?:a+)(?:b+)(\d{3})\1/ | ab123123, aaaabb135135 |
抓取一大段文字中需要的部分
從一大段文字中抽出你要的資訊,以下範例就是抽出email跟電話號碼。
var word = "[email protected] (555) 555-5555 111-222-3333 555 555-5551 [email protected] [email protected]",
regexmail = /([\w\-]+@[\w\.]+)/g,
regexphone = /\(?\d{3}\)?[\s\-]\d{3}[\-\s]\d{4}/g;
document.write(word.match(regexmail) + '<br>' + word.match(regexphone));
email: ([\w-]+@[\w.]+)
[\w-]→ 抓任何單一字元跟- // h,a,n,n,a,h
[\w-]+→ 抓成字串 // hannah
([\w-]+@[\w.]+)→ 把email整個包起來抓
phone: \(?\d{3}\)?[\s-]\d{3}[-\s]\d{4}
\d{3}→ 3個數字 // 111
\(?\d{3}\)? → 3個數字可以被()包起來也可以不要 // 111 or (111)
\(?\d{3}\)?[\s-] → 3個數字後可能會是-或空格隔開 // 111-, 111
\(?\d{3}\)?[\s-]\d{3}→再接3個數字 // 111-222
\(?\d{3}\)?[\s-]\d{3}[-\s]→後面可能會是-或空格隔開 // 111-222-, 111-222
\(?\d{3}\)?[\s-]\d{3}[-\s]\d{4}→ 最後再接4個數字 // 111-222-3333
註冊時的密碼驗證
如果要驗證一段密碼是不是符合下列條件
- 至少有一個數字
- 至少有一個小寫英文字母
- 至少有一個大寫英文字母
- 字串長度在 6 ~ 30 個字母之間
表示式應該寫
^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,30}$
參考資料:使用 Regular Expression 驗證密碼複雜度
練習
用practice.html
撰寫驗證程式碼
- 驗證身分證字號,開頭大寫,第二個字元不是1就是2,如:
A123456789
- 驗證英文名字,大寫開頭,後面小寫,如:
Allen
,Mary
- 輸入時間,如
24:00
,8:45
- 第一個英文字碼代表縣市簡碼,出生報戶口時的戶籍地
- 第二個數字第一碼代表性別,1代表男性,2代表女性
- 第三個字元到第九個字元為流水號碼,按鄉鎮市區及村里別與申報順序配賦
- 第十個字元為檢查號碼
new RegExp(pattern, attributes);
var re = new RegExp("abc"); //RegExp型態,可用exec,test
參考資料: