Regular Expression 正規表達式 快速上手


Posted by Nicolakacha on 2020-09-13

Regular Expression 正規表達式是什麼?

就是用一套事先定義好的符號,來表達資料規則的方式。

Regular Expression 拿來幹嘛?

Search & Replace:可以用它的語法來搜尋或取代指定的字串,不需要傳統的方法做字串處理

Validate:可以拿來驗證某些格式,例如信箱、手機號碼等。

Reformat:可以把某種格式直接轉換成另一種格式

使用 Regular Expression 的好處

語法精簡:在不同的程式語言都可以使用一樣的表達式

速度非常快:效能比用原來的字串方法快

支援度佳:目前很多工具都可以支援正規表達式

規則

頭尾用 / 包住

/abc/

普通字元/abc/

/a/
apple

// a

特殊字元 [^$.|?*+(/

用到特殊符號前面要用反斜線來跳脫

/if \(true/
if (true) { doSomthing() }

// if true

任意字元/./

/a.man/

I'm a man
// a man

abman
// abman

**g 全域範圍**

這個 g 是 global 的意思,如果沒有加上 g,就只會 match 到第一個 match 到的字串:

/a/

a a a a a
// a

/a/g

a a a a a
// a a a a a

多個字元 /[aA]/

/[aA]/g

An apple
// A a

/[aeiuo]/g

There is an apple
// e e i a a e

多個字元的簡寫 /[a-z]/

選出區間之間的字,也可以像第二個例子這樣連用

/[a-z]/g

There is an apple
// here is an apple

/[a-zA-z]/g

Hello World 888
// Hello World

/[1-9]/g

09237487367
// 9237487367

選到不是什麼什麼的字元 ^

/[^H]/g

Hello World
// ello World

/[^0-9]/g

123 hahaha
// hahaha

多個字元的縮寫

\d 數字,就和 [0-9] 的意思相同

\w 英數字和底線,和 [A-Za-z0-9] 的意思相同

\s 空白

/\we/g

There is an apple
// here le

/\d\d/g

I have 10 dollar
// 10

\D 非數字,和 [^\d] 的意思相同

\W 非英數字和底線,和 [^\w] 的意思相同

\S 非空白,和 [^\s] 的意思相同

/\D/g

1 **+** 2 **=** 5 **?
// + = ?**

**\b match 到 \w 的邊界**

邊界就是至少要有一邊為空的意思,例如 This is a book 這個範例,如果只想 match 到 is 的話,可以用 \b 包覆:

/\bis\b/

This is a book
// is

出現的次數

* 出現任意次數

+ 至少出現一次

? 出現零或一次

/l*/g

Hello World
// ll ld

也可以 {} 用這種寫法來指定出現的次數,也可以設置最少和最多次數的範圍:

{次數}

{最少次數, 最多次數}

/l{2}/

He**ll**o Wolrd
// ll

// 只規定最少一次,一次以上都會被選到
/l{1}/g

He**ll**o Wor**l**d
// l l

出現頭尾與結尾

^ 要出現在開頭

$ 要出現在結尾

/^He/

Hello He He Heeee
// He

/llo$/

Heellllo llo
// llo

//開頭是 He 結尾是 llo,中間是任意字串
/^He.*llo$/g

Hello Hello
// Hello Hello

**i 不管大小寫**

Regular Expression 是 case sensitive 的特性,會區分大小寫,後面加上 i 可忽略大小寫:

/ha/g

HA HA ha ha HA
//  ha ha
// 只會選到小寫 ha ha

/ha/gi

HA HA ha ha HA
// HA HA ha ha HA
// 大小寫都會選到

**| 或**

要特別注意的是,使用 OR 若第一個條件已經 match 到了,第二個條件就會直接被忽視:

/and|android/g

iOS and android
// and and

如果要正確 match 到 android,就要反過來寫,讓正規表達式可以先以第一個條件去 match 到 android,而不會像第一種寫法那樣因為已經被 and 條件 match 到而忽略:

/androd|and/g

iOS and android
// and android

範例

身分證字號:

/^[A-Z]\d{9}$/
A123456789

//但實際上身分證字號有一套演算法來判斷有效性
//上面的正規表達式只能簡易驗證格式符合而已

Gmail 信箱:

/^\w+@gmail\.com$/
example@gmail.com

// 開頭至少要有一個英數字 ^\w+
// @gmail 直接拿進來比對
// . 點部份要記得加 \ 來跳脫字元
// 最後是結尾為 .com 的,所以使用 .com$

搭配 JavaScript

字串取代

'banana'.replace(/na/, 'NA')  // 'baNAna'
'banaNa'.replace(/NA/, 'na')  // 'banana'

Capture Group

() 來把一組表達式 match 到的內容捕獲成變數,方便之後引用、取代或做其他操作:

'apple'.match(/(a.)(p.)e/)
// $1 = 'ap'
// $2 = 'pl'

'apple'.replace(/(a.)(p.)e/, $1$2) // 'appl'
'apple'.replace(/(a.)(p.)e/, $2$1) // 'appl'

'2020/09/14'.match(/(.*)\/(.*)\/(.*)/)
// $1 = 2020
// $2 = 09
// $3 = 14
// 得到的陣列會有選到的字串,以及剛才選到的變數
// ['2020/09/14', '2020', '09', '14']

和 JSON.parse 搭配的取代

JSON.parse(
    '2020/09/14'.repalce(
            /(.*)\/(.*)\/(.*)/,
            '{"year": "$1", "month": "$2", "day": "$3"}'
     )
)

// {year: "$1", month: "$2", day: "$3"}

以上的案例都是比較簡單的,實際使用會需要考量很多 edge case,例如真正在驗證 email 的 Regular Expression 可能會長這樣:

function validateEmail(email) {
    const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(String(email).toLowerCase());
}

這種時候可以直接找現成的來用就好,讚讚!

總結

Regular Expression 除了可以用在 JavaScript 之外,也可以在 VSCode、Command Line 或其他環境上面使用,接下來再多多可以利用 Regexr.com 來多多熟悉和測試自己對它的了解~

參考資料:

簡易 Regular Expression 入門指南 by Huli
[線上讀書會] 承億 主講 regular expression
Regular Expressions (RegEx) Tutorial by The Net Ninja
正则基础


#RegEx







Related Posts

Day 2 - MongoDB 的 CRUD

Day 2 - MongoDB 的 CRUD

自駕車 Software Stack 架構介紹

自駕車 Software Stack 架構介紹

MTR04_1120

MTR04_1120


Comments