--- disqus: ahb0222 GA : G-CQ4L16KHK4 --- # 第十八天 Regular Expression正規表達式 > [color=#40f1ef][name=LHB阿好伯, 2021/01/03][:earth_africa:](https://www.facebook.com/LHB0222/) ###### tags: `Python_30` `R & python` ![](https://i.imgur.com/DSYvcuu.jpg) [TOC] 正則表達式或RegEx是一種特殊的文本字符串 有助於查找數據中的規則 RegEx可用於檢查其他數據類型中是否存在某些規則 python中使用 **`re`** 套件執行相關功能 ``` import re ``` 在正式學習之前,先了解一下原生字串 在Python中,表示原生字串,需要在字串前面加上r 例如在使用到上引號 ==\'== 或是反斜線 ==\\== 在程序中會造成錯誤 如果希望字串中 ==\'== 或 ==\\== 可以正常運行需要在字串前面加上r # 建立re正規表達式物件re.compile() 這邊我想先以re.compile()建立re物件的方式去進行字串搜尋 主要是參考[Python 自動化的樂趣:搞定重複瑣碎&單調無聊的工作(第二版)](https://www.books.com.tw/exep/assp.php/gtgrthrst4577/products/0010867440?utm_source=gtgrthrst4577&utm_medium=ap-books&utm_content=recommend&utm_campaign=ap-202104)的方式來學習 ## 搜尋數字 ==\\d== | ==[0-9]== 在正規表達式中\\d代表為0-9的數字也可以表達為[0-9] ```python= import re namRegex = re.compile(r'\d') #建立re物件 mo = namRegex.search('a1') #搜尋相符資料 mo.group() #回傳相符資料 ``` :::success '1' ::: 若是覺得上面的公式太冗長也可以縮減為 ```python= re.search(r'\d','a1').group() ``` ### 符合多次 ==*== | ==+== | =={}== 常見的資料中我們若是想要在字串中尋找像是手機號碼 我們就可以使用 \\d來搜尋 我們知道手機號碼都是以09做開頭接上後面八位數 ```python= import re namRegex = re.compile(r'09\d\d\d\d\d\d\d\d') #建立規則 mo = namRegex.search('我的手機號 0912345678....') #搜尋相符資料 mo.group() #回傳相符資料 ``` :::success '0912345678' ::: 但這樣\\d就需要寫8次很冗長 此時我們就可以使用星號 ==*== 告訴電腦符合0次或多次皆可 或是使用加號 ==+== 符合1次或多次皆可 ```python= import re namRegex = re.compile(r'09\d+') #建立規則 mo = namRegex.search('我的手機號 0912345678....') #搜尋相符資料 mo.group() #回傳相符資料 ``` :::success '0912345678' ::: 但這樣又有可能遇到取得錯誤的資料問題 ```python= namRegex = re.compile(r'09\d*') #建立規則 mo = namRegex.search('家裡電話01-2165409....') #搜尋相符資料 mo.group() #回傳相符資料 ``` :::success '09' ::: 這時候我們就可以使與用大括號 =={min,max}== 來限制我們要的重複數量 ```python= import re namRegex = re.compile(r'09\d{8}') #建立規則 mo = namRegex.search('家裡電話01-2165409....') #搜尋相符資料 mo.group() #回傳相符資料 ``` :::success AttributeError: 'NoneType' object has no attribute 'group' ::: ### 貪婪模式 ==?== 在使用到 ==*== | ==+== | =={}== 時可能會遇到字串中有符合的結果不只一個 例如在前面提到大括弧可以設定符合的次數 設定最大與最小次數 但在正規表達式中預設會比對符合最大的符合資料 ```python= import re namRegex = re.compile(r'\d{6,7}') #建立規則 mo = namRegex.search('12345678') #搜尋相符資料 mo.group() #回傳相符資料 ``` :::success '1234567' ::: ```python= import re namRegex = re.compile(r'\d{6,7}?') #?貪婪模式 mo = namRegex.search('12345678') #搜尋相符資料 mo.group() #回傳相符資料 ``` :::success '123456' ::: #### 符合零次或一次 ==?== ==?== 也可以作為符合零次或一次使用 所以使用上需注意 ## 分組查詢 ==()== 、 字元集合 ==[]== 在Python中可以選擇使用括號將想比對的資料做分組 例如我們市話號碼主要會有一個2 ~ 4碼的區碼加上6 ~ 8碼的數字所組成 若是我們想將兩組號碼區分開來這時候就需要使用到括號 >[長途電話區號表](https://zh.wikipedia.org/wiki/%E4%B8%AD%E8%8F%AF%E6%B0%91%E5%9C%8B%E9%95%B7%E9%80%94%E9%9B%BB%E8%A9%B1%E5%8D%80%E8%99%9F%E8%A1%A8) ```python= import re namRegex = re.compile(r'(\d{2,4})-(\d{6,8})') #建立規則 mo = namRegex.search('家裡電話01-2165409....') #搜尋相符資料 mo.group() #回傳相符資料 ``` :::success '01-2165409' ::: ```python=+ mo.group(1) #回傳第一組相符資料 ``` :::success '01' ::: ```python=+ mo.group(2) #回傳第二組相符資料 ``` :::success '2165409' ::: 更進一步有時候我們收到的資料可能會是使用國際號碼 這時候若是兩種資料我們都想要 那就可以使用中括弧設定特定的集合來選擇我們需要的資料 ```python= import re namRegex = re.compile(r'(\+*[886,0]\d{1,3})-(\d{6,8})') mo = namRegex.search('家裡電話+8861-2165409....') #搜尋相符資料 mo.group(1) #回傳區碼資料 ``` :::success '+8861' ::: 剩下還有許多的規則若是有興趣可以查看維基百科中的[正規表示式](https://zh.wikipedia.org/wiki/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F)寫的也很詳細 # 相關函數 ```python= re.match():僅在字符串第一行的開頭搜索,如果找到則返回匹配的對象,否則不返回。 re.search():如果字符串中的任何地方(包括多行字符串)都存在一個匹配對象,則返回一個匹配對象。 re.findall():返回包含所有匹配項的列表 re.split():獲取一個字符串,在匹配點處將其拆分,然後返回一個列表 re.sub():替換字符串中的一個或多個匹配項 ``` # 尋找相符字串re.match & re.search() :::danger re.match(要搜尋的規則, 目標字串, re.I) re.I是忽略大小寫(re.IGNORECASE的縮寫) ::: ```python= import re txt = 'I love to teach R and python' match = re.match('I LOVE TO TEACH', txt, re.I) print(match) ``` :::success <re.Match object; span=(0, 15), match='I love to teach'> ::: # 使用多行註解模式_re.X 而使用re.X會開啟「詳細(verbose)模式」 之後就可以使用多行字串加上註釋會忽略空白 ```python= import re namRegex = re.compile(r""" (\d{2,4}) #開頭為2~4碼數字 - #中間有一個減號 (\d{6,8}) #最後有6~8碼數字 """,re.X) #最後再加上re.X mo = namRegex.search('家裡電話01-2165409....') #搜尋相符資料 mo.group() #回傳相符資料 ``` :::success '01-2165409' ::: # R語言 R與研究不得不介紹strings套件了 但這部分就留到下次再來分享 不然篇幅真的太大了 https://evoldyn.gitlab.io/evomics-2018/ref-sheets/R_strings.pdf # [好用的線上測試網站_regex101](https://regex101.com/) ![](https://i.imgur.com/8C3UFD2.png) # [Rstudio好用正規表達式套件_remotes](https://github.com/gadenbuie/regexplain) ![](https://i.imgur.com/34aWL2x.png) # 參考資料 https://github.com/Asabeneh/30-Days-Of-Python/blob/master/18_Day_Regular_expressions/18_regular_expressions.md [Python 自動化的樂趣:搞定重複瑣碎&單調無聊的工作(第二版)](https://www.books.com.tw/exep/assp.php/gtgrthrst4577/products/0010867440?utm_source=gtgrthrst4577&utm_medium=ap-books&utm_content=recommend&utm_campaign=ap-202104) 🌟全文可以至下方連結觀看或是補充 https://hackmd.io/@LHB-0222/RegEx 全文分享至 https://www.facebook.com/LHB0222/ https://www.instagram.com/ahb0222/ 有疑問想討論的都歡迎於下方留言 喜歡的幫我分享給所有的朋友 \o/ 有所錯誤歡迎指教 # [:page_with_curl: 全部文章列表](https://hackmd.io/@LHB-0222/AllWritings) ![](https://i.imgur.com/47HlvGH.png)