什麼是 Regex

正規表達式 Regex,全名叫做 Regular Expression,是一個非常強大的工具。

它主要是用來描述某一個字串的特定模型,常常被用在計算機科學和數據分析之中,用來操作以及搜索文字數據。

用白話一點的方式來說,這個工具可以讓我們用極其簡單以及有效的方式來在大量的文字訊息中提取特定的訊息!

基本上,Regex 就是利用一連串的符號來表示想要比對的規則。了解了它的作用後,接下來讓我們更深入了解他究竟有哪些符號,以及每個符號個別的意義是什麼吧!

Regex 語法

Regex 表達式的語法複雜起來可以非常複雜。但語法的組成不外乎就那幾種,所以了解基礎是非常重要的。

以下是一些最常見的 Regex 語法規則:

  • 文字字符:這些是 Regex 模式中最基本的元素。它們在輸入文本中完全匹配相同的字符。比如說,xyz 就是在判斷一個字串有沒有包含 xyz 這連續的三個字符。
  • 字符集合:字符集合匹配其中的一個字符,使用 [] 將文字或數字一網打盡。例如,[abc] 匹配任何一個字符 abc
  • 定位點:定位點匹配文本的位置,而不是文本本身。例如,^ 定位點匹配行的開頭,而 $ 定位點匹配行的結尾。
  • 量詞:量詞指定字符或字符組在輸入文本中可以出現多少次。例如,* 量詞匹配前一個字符或字符組的零個或多個出現次數。
  • 選擇:選擇允許我們匹配幾個可能的模式之一。例如,| 字符匹配其左邊或右邊的模式。

我知道目前這些語法規則對第一次學習的人來說根本就是天書。

但沒關係!看完這章後再回來看這些規則我相信你一定可以了解這些幾本規則的重要性。

接下來,讓我們來講一些範例來看看到底 Regex 怎麼用吧!

Regex 到底怎麼用

在接下來的文章中,我們將利用 RegExr 這個網站來幫我們快速上手並理解 Regex。

在這個網站中,我們可以輸入我們想要的 Regex 表達式,並輸入想要測試的字串,它會告訴我們表達式中的每一個符號的意義,以及有哪些字串被找到,對於新手來說非常方便!

文字字符

首先,讓我們來看最基本的例子:

在 Expression 中,輸入我們想要查找的文字規則,比如說 /abc/ 或是 /456/,接著,在下面的格子中輸入想要測試的文字訊息。標示為藍色的就是代表文字匹配成功!

另外,我們會看到輸入的文字被兩個斜線符號 // 給匡了起來,這個因為在 Regex 中,我們利用 // 來代表起始和結束。

字符集合

接下來讓我們來看 [] 的應用,在前一節我們提到 [] 是字符集合,也就是只要符合 [] 裡的其中一個字符就可以了!

比如說:

我們可以看到在測試字串中,只要有出現在 [] 裡的字符都會被抓出來。

這個可以怎麼用呢?比如說當你今天想要抓出或是比對所有數字時,我們就可以使用 /[0123456789]/,或是更簡單的表示法:/[0-9]/

當然,同樣規則也可以適用在英文字母 /[a-z]/。是不是非常方便呢!

但是人類是懶惰的,還有一種更簡單的表示法,那就是 /\d/。這裡的 d 是代表 digit 的意思,而反斜線 \ 則是特定開頭。所以 /\d/ 就是 /[0-9]/

另一個常用的特別表示法,也就是 /\w/。這裡的 w 則代表 word,除了會比對英文字母外,還會比對數字以及底線。所以 /\w/ 就是 /[_0-9a-zA-Z]/

最後還有一個更為特別的表示法,那就是 /./。這個就是懶惰的極致了!這個代表可以比對任意字符!也就是所有你想得到的字符他都可以代表。

定位點

接下來我們來討論定位點,定位點是用來告訴程式我們想要查找的規則的確切位置。

舉例來說,當現在我們要查找 abc 這個規則時,只要在字串中有出現 abc,那就都會被找到。但今天假如我們只想找開頭是 abc 的字串呢?這就是定位點的功用!定位點有兩種:

  1. 起頭 ^
  2. 結尾 $

利用起頭 ^,如果我們想要找開頭是 abc 的字串的話我們可以這樣寫 /^abc/,而如果想找結尾是 abc 的字串的話則可以這樣寫 /abc$/

對比圖如下:

量詞

量詞可以讓我們規定某個規則可以出現多少次

舉例來說,今天我們要找的規則是連續出現 100 次 apple。當然我們可以直接把它寫下來 /appleapple...apple/,但是這樣的操作非常不實際。

在這樣的情況下我們就可以使用量詞。常見的量詞有下列幾種:

  • *:出現 0 次或多次
  • +:出現 1 次或多次
  • ?:出現 0 次或 1 次

比如說,如果看到一個這樣的表達式 /a*/,那就代表我們要找的規則是 a 這個字母出現 0 次以上的字串。

看看以下的例子,我們就可以清楚地知道量詞的運用方式以及不同量詞的意義了!

誒但是這沒有解決我們一開始的問題啊?我們一開始的問題是要尋找某一個特定字符連續出現 100 次的規則。但上面那三個量詞只能讓我知道是出現 0 次、1 次、還是多次啊。

沒錯!如果要尋找特定次數,我們就需要用到大括弧 {} 來幫助我們。比如說如果要尋找 a 出現 100 次,我們可以這樣寫 /a{100}/

那麼如果要找 apple 出現 100 次的話,我們還需要使用小括弧 (),讓程式知道我們要查找的是字符串,而並非單一字符。因此,我們需要這樣寫 /(apple){100}/

那我們可不可以找 apple 出現 50 到 100 次的規則呢?可以的!我們可以這樣寫 /(apple){50,100}/

如果寫成這樣 /(apple){50,}/,那就是代表只要出現超過 50 次的都符合。

選擇

這個語法就相對容易了,我們可以利用 | 來「選擇」要查找的字符串。

比如說 /ab|cd/ 就是查找字符串 abcd。那麼 /apple(ab|cd)呢?

沒錯,就是先查找 apple 這個字符串後,再看後面的兩個字母是什麼,只要是 ab 或是 cd 那麼就可以成功。

Regex 實際範例

講了這麼多,那到底 Regex 可以用在哪裡呢?

接下來讓我們來看一些常見的應用場景,我們會先從比較簡單的講起,然後慢慢提高複雜度!

身分證字號

這種規則非常簡單!因為每個人的身分證字號都擁有相同的規則,也就是 1 個大寫英文字母 + 9 個數字。

所以 Regex 表達是可以這樣寫:/^[A-Z]\d{9}$/

可以看到我們在結尾處加上了一個 $,這是因為我們要確保如果字串擁有多於 9 個數字的話,那我們就不能選取!

整數

在做資料處理時,我們也可以利用 Regex 來快速查找資料庫中所有的整數:/^[+-]?\d+$/

電子郵件

接下來這個則是稍微複雜了一些,但這個也是一個非常常見的應用方式,常常用在要提取使用者輸入的電子郵件。

它的 Regex 表達可以這樣寫:/^[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/

這裡值得注意的是這個表達式並沒有做更多的規範檢查,但已經可以找到大部分的電子郵件格式。

比如說如果我們看到測試範例的最後一個例子 [email protected],這個很明顯是一個錯誤的電子郵件格式,但依然通過規則審查。這是因為 line.com.tw 這個部分適用於規則中的 [a-zA-Z0-9.-]+ 這個部分,而最後一個 tw 才是規則中的 \.[a-zA-Z]{2,4}$

我們需要提供更為複雜的表達式才可以解決這個問題,但在這章中我想這個範例已經足夠。

日期

日期也是一個非常常用的應用,這邊的日期我們使用 月/日/年 的方式。

Regex 表達式可以這樣寫:/^(0?[1-9]|1[012])[-/.](0?[1-9]|[12][0-9]|3[01])[-/.](19|20)?[0-9]{2}$/

我們可以將這麼長的表達式以 [-/.] 為分水點並分為三段來看:

  1. ^(0?[1-9]|1[012]):月。可以看到中間有選擇 | 符號,因為可能為一到九月或是十到十二月。0? 表示 303 都可以通過。
  2. (0?[1-9]|[12][0-9]|3[01]):日。這基本上和月具有類似的規則,在這裡就不贅述。
  3. (19|20)?[0-9]{2}$:年。這邊我們只同意 19xx20xx 年的年份,如果要更廣的範圍,可以將 (19|20) 替換成 ([1,2][0-9]) 以涵蓋 10xx 到 29xx 年。

結尾

講到這邊就大致講完 Regex 啦。這篇從一開始的什麼是 Regex 講到基本語法然後提供了一些實際應用。

當然 Regex 可以應用的場景以及複雜度遠遠大於這篇文章所提到的,這篇基本上是給初識 Regex 的新手看的,而我覺得提到的內容應該就可以應付大部分的規則了!

希望這篇文章有讓大家學到新知~