正規表達式教學,使用狀態機輔助說明-基礎篇-part 1

許恆修 | Heng-Shiou Sheu
9 min readMar 23, 2018
感謝設計師 Elim 大大幫忙

目錄

  1. 前言
  2. 極度懶人包
  3. Regular Expression 介紹
  4. 基礎語法介紹
  5. 練習用習題
  6. 資料來源

一、前言

主要就是把最近學習到關於 Regular Expression(正規表達式)的內容好好記錄下來,在學習過程中發現這玩意兒,其實不只是工程師的工具,也可以是一般人都能以掌握且在日常生活中使用到的,雖然我不曉得什麼時候用得到,但確實 Regular Expression 會出現在許多地方,為此盡可能簡化入手難度而寫出這系列教學,比較屬於工程師的內容還是有,沒相關知識者不去看也沒差XD。

二、極度懶人包

下方為沒有時間,習慣於一邊吃飯一邊看影片的人們使用,關於這邊文章中所要提到的知識以及操作。

三、Regular Expression 介紹

什麼是 Regular Expression?

Regular Expression(正規表達式)又可簡寫為 Regex,他不是新的東西,而是大家早已會的技能,他是語言,也可以說是程式語言,也有人會說他是強大的工具,這些都是對的,只是大家又不同的角度去看待 Regex,而有不同的心得,Regex 在數學上是狀態機,電腦實作中是採用樹狀結構方式實現,也因為他是程式語言,就代表是可以被維護,被實作,被重寫的,因此每次在寫新的 Regex 同時,用對待其他語言的方式對待他,就不會覺得他是麻煩而且難以學習的新事物了。Regex 是各位早已熟悉的東西,早已熟悉的存在。

==狀態機==
狀態機是表示有限個狀態以及在這些狀態之間的轉移和動作等行為的數學模型。Regex 中 為判斷接收到的事件是否滿足,如果滿足則移動到下一個狀態,直到整個狀態機滿足為止。
==樹狀結構補充==
舉例來說這組 Regex 規則這樣寫 /(ab+c)* + aca/,在樹狀結構表示如下圖所示 ![Tree](https://imgur.com/ZCpuizd.png) 當中優先度為 | 大於 +*? 大於 () 大於 [] 大於 abc 大於 range([a-z]) 大於 縮寫(\w) 大於 空白(\s) 大概就是這樣。

什麼時候使用 Regex ?

其實會使用 Regex 的場合大家早就在使用,最普遍來講就是搜尋,在 Excel 中找尋特定數字,在網頁中尋找特定文字,再任意地方找尋特自文字……等,簡單來說,平常在電腦上按下 ctrl + F 的地方都可以使用 Regex,而且他也早就存在在那,例如下圖所示

網頁開發者工具右上角
IDE當中
Google文件中

只是之前我們不知道他所以不會用它XD,就如同之前所說, Regex 是各位早已熟悉的東西,早已熟悉的存在。生活中不是缺少 Regex,而是缺少發現(誤)。

為什麼使用 Regex ?

Regex 存在在各個地方,Java, .NET, python, Perl…等,不只是程式語言中可以使用,日常生活中使用到 ctrl + f 的地方也可以用到,上一段的圖片已經證明了,這意味著 Regex 不是限定在程式上面,而是可以被普羅大眾掌握的技能,Regex 是學一次,哪裡都可以用(learn once use anywhere),這種效益不是超高的嗎XD,而且撰寫 Regex 也可以讓你嚇嚇旁邊不會的同事或是朋友XD,最重要的是 Regex 可以幫你省下時間,在你要找尋的東西越複雜且越大量時,這種感覺越明顯。

常見問題

這邊列出幾個常見的問題,待我們走過之後的學習,相信這邊的問題,各位都是可以迎刃而解的,甚至比之前不用 Regex 時要簡單許多,也不是說一定要學才會解,而是學完後,可以有不同的解決方式,而且通常比之前輕鬆不少。

身分證字號=>我想知道特定縣市中(例如:花蓮桃園台南嘉義)的男生或是女生數量。

email=> 為阻擋對手成長,我想要阻止特定的hostname在我的服務中被使用。

電話=>我想知道這台電信交換機底下的特定號碼是否已經被註冊。

檔案名稱與延伸檔名=> IMG_XXX.jpg 轉乘 IMG_XXX.PNG

HTML=>請告訴我特定tag中的內容

URL=>https://foobar-maybe:7181/path/to/index.html,幫我抓出這段網址的 port以及 address。

幫我抓出這系列 youtube 的檔案連結。

DTOS=>幫我把這份檔案中所有的數字轉成字串

四、基礎語法介紹

工具介紹

開始學習之前,我得先介紹一下這次所需使用到的工具人 Regex101,這網站除了不會即時把狀態機表現出來之外,其他提供的功能已經滿足我們的需求了,接下來的內容皆是基於 PCRE 編譯版本,所有有些語法若與你熟悉的有些出入,請不要過於驚慌,至於這網站使用方式與介紹請參閱下張圖表 。

Regex101 解說

如果圖片+文字說明還是不懂的話,這裡也有錄製影片幫助各位瞭解如何操作這個網站來學習 Regex 。

廢話這麼多,讓我們開始學習如何使用 Regex 吧!

Match Character(配對字元)

先讓我從簡單的地方開始吧,先從配對字元開始,假設我們有一組 email 帳號,如下所示

  • hangxiu1013@gmail.com
  • hengxiu1013@gmail.com
  • hingxiu1013@gmail.com
  • hongxiu1013@gmail.com
  • hungxiu1013@gmail.com

我們想要抓出其中 gmail 的字樣,在 Regex 中,我們需打上

/gmail/

在 / / 中範圍內的為 regex 規則,也就是我們欲找尋的規則,接著讓我們點開連結,看看實際中是如何被使用的,各位可以看到在email 當中有找到 gmail 的地方都會被顯示出來,各位可以嘗試看看輸入/com/其他的規則來了解運作方式。

Match Number(配對數字)

我們如果要找數字的話,也可以輕鬆反推就是打上

 / 要找的數字 /

例如說/2017/ 或是 /1013/,我們一樣透過連結來了解在實際應用中的樣子 [這個連結](https://regex101.com/r/P1pSz4/26),相信目前為止都是十分直覺的,因為跟過去在找文字沒啥不同XD

Match Character 與 Match Number 在狀態機上的表現

為了徹底了解 Regex 的運作機制,我們一定得要了解 Regex 在狀態機中的表現方式,在上述的例子中,我們想找到 / gmail /,在理解上不是找到 gmail,而是找到 g 再來 m 再來 a 再來 i 再來 l ,直接來看圖吧

https://imgur.com/4tcPjHW.png

如同圖片中的 Node0 接收到事件 g 後,往 Node1 移動,Node1 接收到事件 a 後,往 Node2 移動,以此類推,直到全部配對成功,同理可以應用於上述的 /1013/ 中,而如果 NodeN 接收不同的事件時,狀態機就會倒退回去,倒退回去的動作稱為 backtrack,例如說 在 Node1 時,接收到事件 K,則此時會啟動 Backtrack回去到 Node0,Backtrack的觀念到了 Loop 時會再提一次,只是希望大家記得配對成功與失敗狀態機會有的行為,之後重要例子中也會帶有狀態機,請諸位不用擔心:)

Match Character set(配對集合)

如果 Regex 只有這樣那就大材小用了,我們知道一個一個配對的運作方式了,那我們想要配對的是一個集合的呢?

繼續用上面的 email 做舉例,點我開啟連結,email 中我們可以發現帳號只差在第二個字元aeiou,但我又不可能一一去輸入規則/hang/、/heng/這樣,為此 Regex 提供了集合概念的語法,在 regex 中在集合的語法為 [ ],這次要求中我們輸入

/[aeiou]/ 

如此一來就是配對說屬於 aeiou 這集合中任一個的就算OK,點我開啟連結觀看語法使用方始與解釋。

Match Character set 在狀態機上的表現

這是集合的表現,在狀態機中的表現是很好推的,如下圖所示。

https://imgur.com/N9B1B8K.png

一開始 Node0 接收到事件 h 後,往 Node1 狀態移動,接著收到的事件如果是集合[aeiou]中任一個才往 Node2 移動,這邊請各位留意的是,圖中對於狀態機的跑法,是先從先上方開始跑起,在這例子中就是會先判斷是 a 再來 e……,這樣去跑。

Match Not in Range (配對集合以外)

掌握強大的範圍後,我們也會想,這集合內的不一定會是我要的,也有可能是我不要的, 這時候只要替 Regex 寫上規則 [^] 就樣就可以了,例如說

 /[^a-z]/ 

這表示所有小寫英文字母我都不要,只要這集合以外的,在實際應用中如 這個連結,這裡我先偷渡了範圍的觀念

Abbreviation(縮寫)

很多情況不會那麼簡單,例如在身分證字號驗證時,會期望開頭第一個字一定要大寫,這時候你可能會寫下 [ABCDEFGHIJKLMNOPQRSTUVWXYZ],如此長的規則,只為了做一件事情”找到大寫英文字母”,由於這是很常見的想法,因此在 regex 幫你簡化成 / [A-Z] /,這樣就可以了,數字也是相同 / [0–9] /,而英文數字及_也經常使用到所以出現 / \w / 的縮寫字,這個不是要 match w 也不是要 match \w ,而是與 / [A-Za-z0–9_] / 同義,數字也有縮寫字 / \d /,由於是集合,所以也有集合外的語法,只要改成大寫就可。

/[A-Za-z0–9_]/  同義於 [\w] /
/[^A-Za-z0–9_]/ 同義於 [\W] /
/[0–9]/ 同義於 [\d] /
/[0-9]/ 同義於 [\D] /

各位可以在這個連結來測試上述的規則。

Match any(配對任何)

這是 Regex 中最懶惰的配對方式 / . /,效果是配對任何字元,也就是 any 的概念,例如說 / … /,這樣就是幫我配對任意三個字元,注意到,這個是任意字元,不是代表字母或是數字,而是連同特殊字元也都進去了,點開這個連結,了解運用方式與解析。

--

--

許恆修 | Heng-Shiou Sheu
許恆修 | Heng-Shiou Sheu

Written by 許恆修 | Heng-Shiou Sheu

AI研究員 @喬泰科技,軟體工程師@微光國際,業界講師 @FCU 創能學院,Co-Founder @圖靈文本。專注將科技應用於改善生活中,持續性分享軟體架構設計、前沿人工智慧研究、公司治理等觀念。整合科技、人文思維於一體。聯絡 📪 hengshiousheu@gmail.com

No responses yet