創造一個正規式
正規式的基本結構通常以/開頭以/結尾,來寫個簡單的正規式
1 | var regexp = /xxx/ |
還可以用 JavaScript內建的建構子來創建一個正規式
1 | var regexp = new RegExp('xxx') |
用 tpyeof來檢驗他的型別是什麼
1 | typeof regexp |
可以發現他是物件,JavaScript很多東西都是物件型別,包含陣列和函式。
使用正規式來檢驗字串 test()
先宣告一組簡單的字串
1 | var str = 'This is a book' |
透過 JavaScript正規式所提供的語法 text來檢驗字串使否符合我們的正規式
1 | /a/.test(str) // output: true |
因為 str 的這個字串內有 a這個字母,因此輸出為 ture。
稍微修改一下
1 | /z/.test(str) // output: false |
由於 str 字串內並沒有 z 字母,所以回傳 false。
使用正規式做字串取代 replace()
我們可以透過 replace()方法來做正規式篩選,並取代回傳為 true 的字串內容
1 | var str = 'This is a book' |
將字串內的 ‘is’ 用 ‘xx’ 取代
1 | str.replace('is', 'xx') // output: "Thxx is a book" |
有發現什麼地方怪怪的嗎? 為什麼正規式只取代了 this 中的 is,而忽略的 be動詞 is 呢?
取代多個
剛剛的例子中我們其實並沒有使用到正規式,而是用單純的is 字串做篩選而已,一開始我們就提到,正規式是需要包含 /開頭結尾的。
來修來一下程式碼
1 | str.replace(/is/, 'xx') // output: "Thxx is a book" |
Wait Wait Wait! What? 不對欸不對欸,換成了正規式,輸出結果還是沒有變?
使用正規式取得特定字串 match()
試著取出 HTML 中 h3 標籤間內的文字
1 | let htmlStr = ` |
透過 match 方法做篩選
1 | htmlStr.match(/<h3>.*?<\/h3>/) |
輸出結果
1 | ["<h3>吳先生</h3>"] |
若要取得標籤內文字, 可以透過 () 進行標註
1 | htmlStr.match(/<h3>(.*?)<\/h3>/) |
結果會將 () 符合條件的文字也推入返回的陣列中
1 | ["<h3>吳先生</h3>", "吳先生"] |
Regex Flags
其實是這樣的,正規式另外有若干的模式可以做設定,常見的三種參數有 i、g、m。
他們分別代表 insensitive、global、multi line。
補充:除了上述三種模式以外,還有另外三種比較進階的,分別是
sticky、unicode、single line,是在 ES6 以後出現的模式。
global
全局匹配
預設模式只會取代字串中第一個符合的對象,後面的會直接忽略。
現在我們使用 g 模式,如此一來檢驗的目標中所有符合的對象都會順利被取代。
1 | str.replace(/is/g, 'xx') // output: "Thxx xx a book" |
insensitive
忽略大小寫
一般來說在使用正規式是有區分大小寫的,我們直接看下面的例子。
1 | var str = 'This is a book' |
結果是沒有任何變化的,因為小寫 this和大寫 This是會被判斷為不同的。
修改一下程式碼
1 | var str = 'This is a book' |
加入 i參數,可以忽略大小寫,如此一來輸出結果就如我們所預期的囉!
multi line
多行匹配
這個比較難以敘述,直接用程式碼來說明吧~
1 | var str = 'iPhone4\niPhone5\niPhone6\niPhone7\niPhone8' |

只要在字串內放入 \n 會產生換行的符號,如果這時候來試試看取代會發生什麼事呢?
1 | str.replace(/iPhone/, 'iPad') |
1 | // output: |
和剛才的情況一樣只取代了第一個符合的目標。
诶? 這不是一樣用剛剛學到的
g就可以解決了嗎 ?
來試試看吧
1 | str.replace(/iPhone/g, 'iPad') |
1 | // output: |
確實成功了!
不過!在實際的情況下可能還有意外的事情會發生!
1 | str.replace(/^iPhone/g, 'iPad') |
上面的向上箭頭 ^ 是一個正規式很常見符號,簡單說明一下它的意義,它會去匹配字串的開頭。我們來看看 str.replace(/^iPhone/g, 'iPad')的輸出結果。
1 | // output: |
現在,又只修改到第一個符合的目標了!
怎麼會醬 ?
/^iPhone/ 的定義為開頭符合字串iPhone的目標,在沒有使用 m 模式的情況下,即使有換行,他們也不會被視為一個新的開頭,可以想像字串就相當於
'iPhone4iPhone5iPhone6iPhone7iPhone8'
這樣的一大串文字,他們的開頭是 iPhone4中的iPhone字眼。
現在我們來修改一下程式碼
1 | str.replace(/^iPhone/gm, 'iPad') |
輸出結果
1 | "iPad4 |
常用情境
資料驗證
有沒有經驗是當你在註冊某些網站的服務時,當你輸入 E-mail 格式不包含 @ 或是一些 .時,網站會有格是錯誤提示,這是怎麼做到的呢?
1 | //please input the test email to see is valid |
上網搜尋一下正規式 表單驗證其實就很容易找到相關的程式碼了。
由於 E-mail 的格式是固定的,為了避免用戶錯誤輸入,將必定驗證不過的E-mail格式傳到資料庫,消耗不必要的資源,通常在前端我們就會透過正規式的技巧來做簡單的篩選。
搜尋功能
相信會看到這篇文章的各位,大部分都有使用文字編輯器。像是筆者使用的文字編輯器是 VS code,我非常常使用到 ctrl + shift + F 的搜尋功能,以往都是使用單純的字串搜尋,但其是現在有非常多的文字編輯器( 或是其他服務 ),都有提供正規式搜尋功能,學會了以後對於資料的篩選精確度會有非常大的提升!

regex101 正規式測試服務
這是一個正規式測式的服務,提供正規式的撰寫測試。
Regex101 Website
設定程式語言
進入網站第一件事情需要先設定程式語言,雖然幾乎所有程式語言都支援正規式,但之中還是有些微差異,有些功能並不是每個程式語言都會支援,但總體來說大概有80%的語法在所有語言都通用。

因為筆者是Web前端開發者,所以這邊我選 JavaScript。
基本功能說明

常用字元
字面值
如 a b c d 1 2 3 4 等等指定字。
字符類
. [abc] [a-z] \d \w \s
.表示任何字符[abc]括號表示找到集合裡任意一個字符。\d表示一個數字,等同於[0-9]\w表示一個單詞字符,等同於[0-9A-Za-z_]\s表示一個空格,tab,回車或一個換行符[^abc] \D \W \S: 否定字符類,和上述同字母小寫的意義相反
乘法器
{4} {3,16} {1,} ? * +
{3,16}表示找到重複3 到16 次內的字元?表示”沒有或出現一次”*表示”沒有或出現多次”+表示”一個或出現多次”
分支和組合
(Septem|Octo|Novem|Decem)ber
- 符號
|表示”或” - 圓括號表示組合,比如在一周中找到一天,使用
(Mon|Tues|Wednes|Thurs|Fri|Satur|Sun)day。
詞、行和文本邊界
^表示行開始$表示行結束
反向捕獲組
比如有一段字符,我們需要前面的橫槓去掉,英文句號換成橫槓,尾巴的數字去掉,但是編號及文章標題需要保留。
1
2
3
4
5-1.文章標題1
-2.文章標題2
-3.文章標題3
-4.文章標題4
-51.文章標題5
將上文宣告成一組換行字串
1 | var str = '-1.文章標題1\n-2.文章標題2\n-3.文章標題3\n-4.文章標題4\n-51.文章標題5' |
我們預計要將字串替換成 [編號]-[標題]
我們的正規式為 / - (\d+) \. (.+) \d+ / g
| RegEx | 代表意義 |
|---|---|
- |
固定字串 |
★ (\d+) |
至少一位數的數字(編號),小括號內的值之後可以用$1輸出 |
\. |
固定字串,由於dot在正規式是有意義的,須以反斜線標記,代表為固定字串. |
★ (.+) |
至少一個字的任意字元(標題),小括號內的值之後可以用$2輸出 |
\d+ |
至少一位數的數字 |
g |
全局匹配 |
而其中$1 $2分別代表正規式中小括號內的字串,他們是由左自右排列的,舉例來說若將 (\d+)的小括號移除,則後面的 (.+)往前遞補,變成 $1的參考值,$2則不存在了。
有時候我們需要括號來作區隔,但是不希望它形成一個群組,意即不希望小括號內的值成為
$的參考值時,我們可以在小括號的前方加上?:,就可以把群組取消。如例子中可以將(\d+)改為(?:\d+),這麼一來現在的$1參考到的值是(.+),而$2則不存在了。
使用replace()方法替換內容。
1
str.replace(/-(\d+)\.(.+)\d+/g, '$1-$2')
1 | // output: |
空白字元
- 直接打空白鍵 → space
\t→ TAB\n→ 換行\r→ 回車符\s*→ 所有空白字元
其他
預查
正向預查
(?=)
有時候我們希望匹配的字串符合某個條件,但不希望該條件也被選取
反向預查
(?!)
(?=)&(?!)和上面補充的(?:)相同,都不會使小括號內值被群組。
參考資料
[偷米騎巴哥]正規式苦手超入門
Jark’s Blog - 正則表達式學習
正規式語法大全
常見正規式範例 - Email 正規式
常見正規式範例 - 驗證整數和小數的正則表達式