什麼是正規表達式 Regular expressions
英文 Regular expressions 譯為常用表達,在中文的別名有稱為正則表達式、正規表示法、正規式等…
 Regular expressions 是在 UNIX 中發展出的字串比對技巧,其基本概念用簡單(但強大)的符號來比對字串,並可對符合比對條件的字串進行修改或其他運算。
 在軟體工程中,很多的地方都會透過正規表達式 (正則表達式) 來進行字串或字元的比對判斷,像是資料庫語法、後端程式語言、輸入指令核對塑等…
是一種用來描述字串符合某個語法規則的模型 (pattern),可用來文字的搜尋、比對、萃取、替代、轉換等等,在許多的程式語言中都支援正規表達式的使用。
在網頁前端開發上來說,以 JS 為主的自動化流程工具 (webpack or gulp) 、HTML 網頁前端輸入框輸入時直接回饋,也都能以這樣簡潔的方式來設計與運用。
 例如:訂單規則 b1234567890 (B 開頭後十碼),類這樣的方式就正規表達式的規劃。
JavaScript 的 RegExp 規劃正規表達式
JavaScript 的正規式是一個內建的物件,其建構函數(Construction functoin)為 RegExp,兩個斜線 / / 或是 new RegExp() 來建立一個 RegExp 物件。
參數一:pattern﹙模型﹚ / 參數二:flag﹙標籤﹚
參數一:pattern﹙模型﹚的 literal 與 new RegExp() 建構函式物件寫法
在基本的撰寫上可只用一個參數的方式。
1 2 3 4  | // 1. 使用 literal 方式在 script 載入時就被編譯,效能較好。 const regex = /some text/; // 2. new 建構一個 RegExp 物件,適用在需要動態產生 pattern 的場合。 const regex = new RegExp('some text');  | 
參數二:flag﹙標籤﹚配和字符做細部的批配方式
第二個參數 flag (標籤) 加上設定,能做更細部的批配方式。
– g:全域比對(Global match)
 – i:忽略大小寫(Ignore case)
 – gi:全域比對並忽略大小寫
1 2  | const regex = /some text/i; const regex = new RegExp('some text', 'g');  | 
了解 JavaScript 的 new RegExp() 與 literal 二種正規表達式的方式,以下先透過 .test() 方法針對使用單一個參數展示用法。
1 2 3 4 5 6 7 8  | const regex_literal = /hello/; // 宣告正規表達式規則 regex_literal.test('hello'); // true regex_literal.test('hello123'); // true regex_literal.test('123hello123'); // true regex_literal.test('123hello'); // true regex_literal.test('Hello'); // false 如果英文單字前方使用 H 大寫,此時會回應錯誤  | 
使用第二個參數 flag (標籤) 寫法,針對先前的驗証方式做出調整。
1 2 3 4 5  | const regex_literal_i = /hello/i;  regex_literal_i.test('hello'); // true regex_literal_i.test('HelLo'); // true regex_literal_i.test('123HelLO'); // true   | 
RegExp 與 String 原型方式,使用正規式
g : global 的意思,找到之後會繼續往後配對。
1 2 3  | const regex_literal_g = /hello/g;  regex_literal_g.test('hello'); // 輸入瀏覽器 console 時顯示是 true,但表達式回傳確是 false  | 
但很怪是在用 .test() 方法使用時,回應出來的結果確是不同,明明查驗的部份都是 hello,但確回傳的是 false,原來 .test() 方法所處理的對象是 RegExp,這部份就與 .exec() 一樣。
 RegExp.prototype.test():搜尋字串中是否有符合的部分,回傳 true/ false。
 RegExp.prototype.exec():以陣列回傳字串中匹配到的部分,否則回傳 null。
想要看字串是否包含某 pattern 時,使用 test 或 search;
想要更多的資訊(花較多耗效能),則使用 exec 或 match。
 String.prototype.match():以陣列回傳字串中匹配到的部分,否則回傳 null。
 String.prototype.replace():尋找字串中匹配的部分,並取代之。
 String.prototype.search():尋找字串中是否有符合的部分,有的話回傳 index,否則回傳 -1。
 String.prototype.split():在字串根據匹配到的項目拆成陣列。
在此, g 的用法指的是批配後會接著在處理,所以另外改用 .replace() 的字串處理方法進行查找後做更換的動作,這樣就可以了解到批配的原理,特別將字串只查找 ll。
1 2 3 4 5  | const regex_literal_g = /ll/g; 'hello'.replace(regex_literal_g, 'LL'); // "heLLo"  'hellohello'.replace(regex_literal_g, 'LL'); // "heLLoheLLo"  'hellllo'.replace(regex_literal_g, 'LL'); // "heLLLLo"   | 
character﹙特殊字元﹚
1  | const str ='This is a string';  | 
^:pattern 必須在字串的開頭
1 2  | str.match(/^This/); // Array [ "This" ] str.match(/^THIS/); // null  | 
$:pattern 必須在字串的結尾
1 2  | str.match(/This$/); // null str.match(/string$/); // Array [ "string" ]  | 
|﹙or 或﹚:前後字串都比對
1 2 3 4 5 6 7 8  | const colorRE = /color|colour/;  colorRE.test('color'); // true colorRE.test('colour'); // true colorRE.test('colours') ; // true colorRE.test('colors'); // true colorRE.test('colo'); // false  colorRE.test('colou'); // false   | 
\﹙反斜線﹚:比對特殊符號跳脫特殊字元
比對特殊符號時,使用反斜線 \ 來跳脫特殊字元。
1 2  | const regex = /\$100/ regex.test('$100') // true  | 
.:任意一個字元前後批配 (類 PHP . 方式組字串)
針對單一個字元進行前後字元組合的批配。
1 2 3 4 5 6 7 8 9  | var a_before_regex = /a.man/; // a*man 都會 match,例如 "acman", "awman", 但 "a\nman" 無法匹配。 a_before_regex.test('acman'); // true a_before_regex.test('awman'); // true a_before_regex.test('a\nman'); // false  var a_after_regex = /.a/; // 任何一個字元後加上 a a_after_regex.test("a"); // false  a_after_regex.test("aa"); // true  a_after_regex.test("1a"); // true  | 
[]:多個字元
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16  | // 只要是英文大寫字母,就比對成功 const regex = /[ABCDEFGHIJKLMNOPQRSTUVWXYZ]/ 'K'.match(regex) // ["K", index: 0, ...] 'δ'.match(regex) // null // 可以使用 '-' 來簡化集合,'A-Z' 表示英文字母 A ~ Z 都符合 const regex = /[A-Z]/ // 小寫 a 或大寫 A var regex = /[aA]/; // 若要比對的是英文或數字,可以這樣表示 const regex = /[A-Za-z0-9]/ // 匹配所有不是 a 或 A 的字 var regex = /[^aA]/;  | 
集合有對應的特殊字元,可視為縮寫。
1 2 3 4  | const regex = /./   // 比對換行符號外的任意一個字元 const regex = /\d/  // 比對一個數字,相等於 /[0-9]/ const regex = /\w/  // 比對一個英文、數字或底線,相等於 /[A-Za-z0-9_]/ const regex = /\s/  // 比對一個的空格 (ex: space, tab, 換行, ...)  | 
使用 ^ 排除。
1 2 3 4 5 6 7 8 9  | const regex = /[^\w]/ regex.test('a') // false regex.test('!') // true /* 不是 a 都會 match */ var regex = /[^a]/; /* 不是數字都會 match */ var regex = /[^0-9]/;  | 
() ﹙括號﹚:套用到所有
1 2  | var regex = /^a|^the|^an/; // 套用到裡面所有的 var regex = /^(a|the|an)/; // 等同於  | 
實例
身份證字號一個英文字母加九個數字組合
身份證字號的格式是由一個英文字母加上九個數字組合而成,要求使用者輸入身份證字號,以使用 JavaScript 的正規表示法來驗證其格式的正確性。
1 2 3 4 5  | <form>   身份證字號:   <input type="text" value="A12345678" onBlur="checkID(this.value)" />   (第一個英文字母需大寫) </form>  | 
1 2 3 4  | function checkID(string) {   re = /^[A-Z]\d{9}$/;   if (!re.test(string)) alert('你的身份證號碼格式不對!'); }  | 
/^[A-Z]\d{9}$ 正規表達式說明如下。
- ^:代表字串開始位置。
 - [A-Z]:代表由 A 至 Z 的所有可能英文字母
 - \d:代表由 0 至 9 的數目字(事實上也可以寫成 [0-9])
 - {9}:則代表需要有九個數目字。
 - $:代表字串結束位置。
 
若不限大寫英文字母,只需將正規式改成 /^[a-zA-Z]\d{9}$/g 就可以了!
若不加入 ^ 和 $ 表達一個句子的開頭與結尾,那麼 /[A-Z]\d{9}/ 就會比對到其他不合法的身份證字號。
例如 AGF123456789 或是 F1234567890 等。
因此,加入 ^ 和 $ 可保證比對正確的字串,一定是由一個大寫英文字母加上九個數字所構成。
身分證號碼的驗證規則:
一般對身份字號的認知共有 10 位,位第一位為英文字母,第二個數字是男女生之分,男生為 1,女生為 2,接下來的一陀數字。
身份證字號後面八個數字不是隨便打,但前面七個可以隨便打,但是最後一位為檢查碼,必須經過之前一個字母與8個數字的組合計算後得出。
wiki 中華民國國民身分證
信用卡號碼
簡單的 JS 判斷
1 2 3 4  | const card_re = /^\d{4}-\d{4}-\d{4}-\d{4}$/; // 輸入字串 '1111-1111-1111-1111' card_re.test('1111-1111-1111-1111'); // true  | 
實際在網頁中,透過 onBlur 事件去觸發。
1 2 3 4 5 6 7 8 9  | <form>   信用卡號碼:   <input     type="text"     value="xxxx-xxxx-xxxx-xxxx"     onBlur="checkCreditCard(this.value)"   />   (格式:xxxx-xxxx-xxxx-xxxx) </form>  | 
1 2 3 4 5  | function checkCreditCard(string) {   re = /^\d{4}-\d{4}-\d{4}-\d{4}$/;   if (!re.test(string))     alert('你的信用卡號碼不符合「xxxx-xxxx-xxxx-xxxx」的格式!'); }  | 
SCSS webpack 工具,處理不批配檔名開頭不為 _ ﹙下底線﹚,批配多種副檔名
在 webpack 透過 loader 的一段程式碼,例如 loader: 'sass-loader' 取用指定的 sass 與 scss 副檔名,透過 test: /\.(sass|scss)$/, 做為取用對象,這個原理也是正規表達式所處理的。
結合先前所了解操作方式,直接用程式碼來使用,在 SCSS 的使用上所拆分出去的模組或連結檔,多半會在檔名前面加上 _ 做為排除對象。
1 2 3 4  | const SCSS_re = /^(?!_).*.(\.sass|\.scss)$/ SCSS_re.test('aa.scss'); // true SCSS_re.test('_aa.scss'); // false SCSS_re.test('aa.sscss'); // false  | 
 /^(?!_).*.(\.sass|\.scss)$/ 以下說明
 – 前後 // 宣告為正規表達式。
 – ^ 查驗內容的語句開頭、 $ 為結尾。
 – (?!_) 做為開頭也就是檔名前的 _ 下底線,做為排除對象。
 – .*. 整段語句的接續開頭之後的地方,直到結尾副檔名前。
 – (\.sass|\.scss) 包含著內容對象,指定 sass 與 scss 做為對象,而 \.sass 來說是真接處理成 .scss 字串,讓正規表達式了解副檔名的判斷範圍,沒加上 \ 反邪線會連包著著的 .sscss 對判斷通過。
參考資料:正規表示式排除特定字串
參考資料
– 課程筆記-第四週:期中考:打造全端 (Full Stack) 網站架構﹙Node.js直播班-2022春季班﹚ > (關鍵字搜尋與篩選,透過 JS 的正規表達式 new RegExp() 轉成 mongoDB 使用的 /<過濾用字串>/ 格式,不是 JS 的字串格式所能實現)
 – MDN:正規表達式、使用正則表達式校驗
 – Regular Expression (regex),要成為GA專家一定要懂的正規表示式
 – 五倍紅寶石:十五分鐘認識正規表達式,解決所有文字難題
 – 保哥:使用 Regular Expression 驗證密碼複雜度
 – 正規表示法:表單資料驗證 (說明在 JS Regular expressions 的概念與運作方式)
 – pjchender – [JS] 正則表達式(Regular Expression, regex)
 – 使用正規表示法分組 (比對 HTML 標籤與次數)
 – IT人 – javascript常用的正規表示式
 – 程式柴 CodeShiba – 【 初學者教學 】 一小時正規表達式教學 Regular Expression Tutorial (有包含直接在線上程式教學破關方式解題)
