Github完整程式碼連結. “給自己的Python小筆記 — 強大的數據處理工具 — 正則表達式 — Regular Expression — regex詳細教學” is published by Chwang.
GetunlimitedaccessOpeninappHomeNotificationsListsStoriesWrite給自己的Python小筆記—強大的數據處理工具—正則表達式—RegularExpression—regex詳細教學Github完整程式碼連結哈囉,今天想來講一個我在工作上,常常需要用到的工具,我常常需要在一整堆的系統資訊、SystemTrace等等資料中,萃取出我需要的資料,並自動整理成表格的形式,這時候強大的正則表達式(RegularExpression,regex)就幫了我一個很大的忙,所以今天就來一起好好的學習它吧正則表達式是什麼?對於我而言,它是一個非常強大且實用的字串處理方法,它幫助我們從擁有大量字符的文本中,取得我們所需的資訊正則表達式(RegularExpression、regex、regexporRe)透過我們自行定義的字符串規則,幫助我們從文本中找尋對應規則的字符串過濾出我們所需的資料後,幫助我們將這些資料組成串列,方便我們對文本進行下一步的分析舉個例子:我們要在文章中的眾多文字資料中,找尋文章提到的人物的身份證資料,我們就會去定義一個規則,第一個字符要是大寫的英文,後面要接續著九個數字,接著它就會根據這個規則找尋匹配的字符串,收集好後,回傳給我們Python與正則表達式?正則表達式是一種輕量型的程式語言,它並不是Python底下的一個套件而已,像是我也用過Javascript來使用正則表達式處理文本字符串資料,在Python中,我們只要引入re模組就能使用這個強大的字符串處理語言囉基本的匹配補充:常見的[…]匹配規則定義好的字符集邊界上的匹配數量上的匹配(通常用在其它匹配符之後)補充group():簡單來說,就是幫助我們方便看出匹配出來的字符有哪些邏輯與分組的概念特殊用法(不是用於分組)轉義字符特殊情況:當需要匹配一些在正則表達式中有特殊意義的字符時,像是\d、\w、\s等,此時就要多加一個””正則表達式的修飾符號大部分的正則表達式函數中,都會有一個參數flags,它是用來控制匹配的模式的,裡面有如下表的標誌可以供選擇,如果想一次指定多個標誌,可以使用OR(“|”),像是re.I|re.S等組合正則表達式的貪婪與非貪婪模式通常在過程中匹配的字符數量,會有兩種情況:貪婪與非貪婪,而Python中的預設模式為貪婪模式貪婪:,不斷嘗試匹配更多的字符非貪婪:盡可能的嘗試少匹配字符,它會盡量減少匹配重複的字符程式碼舉例:importre##貪婪模式print(re.search('go*','goooooood').group())##'gooooooo'##非貪婪模式print(re.search('go*?','goooooood').group())##'g'執行結果gooooooog怎麼使用非貪婪模式呢?我自己的實作心得是在語法後面加上一個”?”,如下圖的非貪婪模式介紹非貪婪模式的常見用法.*?的用法介紹.*?:盡量匹配較少的字符大多用在像是.*?a的地方,意思是前面匹配任何的字符,直到字母a出現re.search('.*?e','a_b*cdefg').group()正則表達式的函數介紹與實作1.match函數用法re.match會從文本中的起始位置開始進行文字符的匹配,如果不是一開始第一個字符就匹配成功的話,就會直接返回一個none,簡單來說就是欲匹配的文本一開始就要符合我們定義的字符規則,不符合直接回傳none,符合就會回傳字符位置資訊函數語法格式re.match(pattern,string,flags)參數介紹pattern:匹配的規則,使用正則表達式的語法撰寫string:要進行匹配的字符串flags:設定一些正則表達式的匹配方式,像是規則是忽略大小寫,或使用UNICODE字符規則來解析字符等,如果沒有特別需求,可以忽略不寫可以選擇的標誌,可以參考我上面有提到的正則表達式修飾符號使用group()函數來獲取匹配的字符,而不是返回一個字符的位置groups():將匹配好的字符組合起來,形成一個tuple元數組group(num=0):選擇第幾個匹配好的字符程式碼舉例1importretext='https://matters.news/@CHWang'text1='Matters.news'print(re.match('https',text))print(re.match('https',text).span())print(re.match('matters',text))print(re.match('matters',text1))print(re.match('matters',text1,flags=re.I))執行結果(0,5)NoneNone程式碼舉例2:關於group的用法importretext='JacklivesinHsinChuandheis25yearsold,but...'match_result=re.match(r'(.*)livesin([a-z]*)andheis(\d+).*',text,re.I)print(match_result.group())print(match_result.group(1))print(match_result.group(2))print(match_result.group(3))print(type(match_result.groups()))print(match_result.groups())執行結果JacklivesinHsinChuandheis25yearsold,but...JackHsinChu25('Jack','HsinChu','25')2.Search函數用法re.search會搜尋整個字符串,然後找到匹配的字符並且傳回,如果失敗,沒有匹配到任何字符則傳回none,如果成功,就會傳回一個匹配的對象,就可以使用group()來取得匹配成功的字符函數語法格式re.search(pattern,string,flags)參數的用法與match是一樣的喔,這邊就不在說明程式碼範例1importretext='https://medium.com/@chwang12341'text1='Medium.Com'print(re.search('https://',text))print(re.search('dium',text))print(re.search('medium',text).span())print(re.search('co',text1))print(re.search('co',text1,flags=re.I).span())執行結果(8,14)None(7,9)程式碼範例2:使用groups()與group(num)來取得字符importretext='Jenlikestoeatcakeanddrinkcoke,but...'match_result=re.search('(.*)likestoeat(\w+)anddrink([a-z]*)',text,re.I|re.M)print(match_result.group())print(match_result.group(1))print(match_result.group(2))print(match_result.group(3))print(match_result.groups())執行結果JenlikestoeatcakeanddrinkcokeJencakecoke('Jen','cake','coke')小筆記:大家有看出match與search的差別嗎?其實差別就在match一定要從起始位置開始匹配成功,而search則不用的喔!!3.findall函數用法re.findall會直接找尋所有匹配的字符,裝進串列後返回,如果沒有找到匹配的字符,就會回傳一個空的串列喔小筆記:re.findall會匹配所有符合規則的字符,而re.search與re.match只會匹配一次而已喔函數格式findall(pattern,string,pos,endpos)參數說明pattern:匹配的規則,使用正則表達式的語法來撰寫string:欲進行匹配的字符串pos:可選擇的參數,不一定要寫,指定開始匹配的位置,預設為0,也就是起始字符的位置endpos:可以選擇的參數,不一定要添加,指定結束匹配字符串的位置程式碼舉例:importrefind_pattern=re.compile(r'[a-z]+',re.I)match_result1=find_pattern.findall('good66dayTom_28Yep')match_result2=find_pattern.findall('good98MMorning66Jen666Yeah',6,20)print(match_result1)print(match_result2)執行結果['good','day','Tom','Yep']['MMorning','Jen']4.sub函數用法匹配好字符後,將它替換成我們想要的字符,這個方法相當方便,我們在進行數據處理時,有時候會有一些多餘的不要的空格、符號等等,就可以透過這個方法來一次拿掉函數語法格式re.sub(pattern,repl,string,count=0,flags)參數解釋pattern:匹配的規則,使用正則表達式的語法來撰寫repl:欲替換的字符,也可以用函數的形式傳入喔string:要進行匹配的字符串count:匹配好字符後,替換的最大數量,預設為0,表示要全部替換flags:設定一些正則表達式的方式,像是規則是否忽略大小寫、使用UNICODE字符規則來解析字符等,如果沒有特別需求可以忽略不寫可以選擇的標誌,可以參考我上面有提到的正則表達式修飾符號喔程式碼舉例1:importretext='Jack/25/1993andJen/23/1995'##把中間的and與空格拿掉,用&替換sub_result1=re.sub('\sand\s','&',text)print(sub_result1)##狀況一:再把/拿掉sub_result2=re.sub('/','',sub_result1)print(sub_result2)##狀況二:再把/拿掉,但只要拿掉前兩個sub_result3=re.sub('/','',sub_result1,2)print(sub_result3)執行結果Jack/25/1993&Jen/23/1995Jack251993&Jen231995Jack251993&Jen/23/1995程式碼舉例2:repl使用函數傳入時importretext='Jack66Jen58Ken28,Cathy38'##將匹配好的數字做平方計算defsquare(match_result):num=int(match_result.group('number'))returnstr(num**2)##給定我們匹配值一個名稱,用?Pfinal_result=re.sub('(?P\d+)',square,text)print(final_result)執行結果Jack4356Jen3364Ken784,Cathy14445.Compile函數re.compile可以幫助我們編譯正則表達式,並生成一個pattern對象,來供給match、search、findall函數使用,簡單來說,就是我們只要定義好一次正則表達式的規則,就能用這個定義好的pattern規則,來提供match、search、findall函數匹配字符用了這個方法後,我們就不用每次使用匹配函數時,都要重新寫一次正則表達式語法,但明明匹配的規則與寫法是一樣的函數語法格式:re.compile(pattern,flags)參數介紹pattern:匹配的規則,使用正則表達式的語法來撰寫flags:設定正則表達式匹配的一些模式程式碼舉例:importretext='68Jack66Jen58Ken28,Cathy38'##匹配字母,並忽略大小寫pattern=re.compile(r'([a-z]+)',re.I)##match預設從第一個位置開始匹配compile_result1=pattern.match(text)print(compile_result1)##None,因為match會從第一個位置開始匹配,如果不通過就會返回none##從第3個位置開始匹配compile_result2=pattern.match(text,2,20)print(compile_result2)print(compile_result2.group(0))print(compile_result2.start(0))print(compile_result2.end(0))print(compile_result2.span())執行結果NoneJack26(2,6)補充用法說明group():匹配好後,會回傳一個tuple,會根據匹配成功的字符一組一組返回,但由於match方法只會回傳一組,所以只要寫group()就好,其他的話,諾我們想要回傳第一組就寫group(0),以此類推start():起始位置,傳入要查詢的組別,像是第一組就寫start(0),以此類推end():結束位置,傳入要查詢的組別,像是第一組就寫end(0),以此類推span():傳回(起始位置,結束位置)6.finditer函數用法re.finditer的用法與re.findall相似,找到所有符合匹配規則的字符後,以迭代器的形式傳回函數語法格式:re.finditer(pattern,string,flags)程式碼舉例:importrematch_result=re.finditer(r'[a-z]+','68Jack66Jen58Ken28,Cathy38',re.I)fornameinmatch_result:#print(name)print(name.group())執行結果JackJenKenCathy7.split函數用法re.split將匹配的字符進行切割,並且回傳一組串列函數語法格式:re.split(pattern,string,maxsplit,flags)參數介紹pattern:匹配的規則,使用正則表達式的語法撰寫string:欲進行匹配的字符串maxsplit:分割的次數,如maxsplit=1,代表分割一次,預設為0,表示不限分割次數flags:設定一些匹配的模式程式碼舉例:####importretext='Jack66Jen58Ken28Cathy'##用數字來做為分隔依據print(re.split('\d+',text))##分隔,並將數字也傳進陣列print(re.split('(\d+)',text))##如果匹配的一句剛好在前後的位置,就會傳回空值text1='66Jack66Jen58Ken28Cathy38'print(re.split('\d+',text1))##如果找不到匹配會回串全部字串print(re.split('\s+',text1))執行結果['Jack','Jen','Ken','Cathy']['Jack','66','Jen','58','Ken','28','Cathy']['','Jack','Jen','Ken','Cathy','']['66Jack66Jen58Ken28Cathy38']重要筆記:匹配時將我們需要爬取的數據,用()來包住它的匹配規則,才會被獨立出來放入串列舉個例子來說,我們想要爬取文本字符串中符合我們指定格式的字符串,但是我們只想要取得|Example_format|前後的數值,並分別放入串列,這時候我們就需要將它們括號起來,像是(\d+)|Example_format|(\d+)這樣指定的字符串格式:6658|Example_format|666程式碼舉例:importretext='6658|Example_format|2020'print(re.findall(r'(\d+)(?:\WExample_format\W)(\d+)',text))執行結果[('6658','2020')]這樣的話,之後大家就可以在有很大量字符串的數據文本中,爬取符合我們需求格式的資料,而且我們不只要爬取符合這個格式的資料,還要只收集我們在這個格式中需要的數據值太好了,會了強大的正則表達式(RegularExpression)後,我們就能在茫茫文字海中爬取各種我們所需的資料囉,真的超級實用!!感謝大家的閱讀,如果覺得我寫得還行XD,在幫我拍拍手鼓勵一下,或有問題也可以在底下留言跟我討論討論喔~~Referencehttps://www.itread01.com/content/1552631899.htmlhttps://www.runoob.com/python/python-reg-expression.html#flagshttps://kknews.cc/zh-tw/code/mjnv352.htmlhttps://docs.python.org/zh-tw/3/howto/regex.html--2MorefromChwangFollowYO~~大家好我是一名AI人工智慧領域的小小工程師,熱愛自學,熱愛分享,下班後的我想為自己Coding,積極撰寫教學文,想將自學的程式知識分享給大家,不斷追求進步的自己,希望有一天能回饋社會,幫助需要幫助的人,如果您有什麼很酷的想法,也覺得我還行,歡迎您找我合作~~Lovepodcastsoraudiobooks?Learnonthegowithournewapp.TryKnowableAboutHelpTermsPrivacyGettheMediumappGetstartedChwang80FollowersYO~~大家好我是一名AI人工智慧領域的小小工程師,熱愛自學,熱愛分享,下班後的我想為自己Coding,積極撰寫教學文,想將自學的程式知識分享給大家,不斷追求進步的自己,希望有一天能回饋社會,幫助需要幫助的人,如果您有什麼很酷的想法,也覺得我還行,歡迎您找我合作~~FollowMorefromMediumfly'xivPythonicWay1:Intro,RangeHafizumairMemoryManagementinPythonKartheekSunkaraPythonRegEx — FindnextwordhamzakhanPush-upCounterUsingPython(WithMediapipe)HelpStatusWritersBlogCareersPrivacyTermsAboutKnowable