day34-常見內建模組三(re模組)
阿新 • • 發佈:2018-12-03
re模組
1、什麼是正則
正則就是用一些具有特殊含義的符號組合到一起(稱為正則表示式)來描述字元或者字串的方法。或者說:正則就是用來描述一類事物的規則。(在Python中)它內嵌在Python中,並通過re模組實現。正則表示式模式被編譯成一系列的位元組碼,然後由用C編寫的匹配引擎執行。
元字元 匹配內容
\w 匹配字母(包含中文)或數字或下劃線
\W 匹配非字母(包含中文)或數字或下劃線
\s 匹配任意的空白符
\S 匹配任意非空白符
\d 匹配數字
\D 匹配非數字
\A 從字串開頭匹配
\Z 匹配字串的結束
\n 匹配一個換行符
\t 匹配一個製表符
^ 匹配字串的開始
$ 匹配字串的結尾
. 匹配任意字元,除了換行符,當re.DOTALL標記被指定時,則可以匹配包括換行符的任意字元。
[...] 匹配字元組中的字元
[^...] 匹配除了字元組中的字元的所有字元
* 匹配0個或者多個左邊的字元。
+ 匹配一個或者多個左邊的字元。
? 匹配0個或者1個左邊的字元,非貪婪方式。
{n} 精準匹配n個前面的表示式。
{n,m} 匹配n到m次由前面的正則表示式定義的片段,貪婪方式
a|b 匹配a或者b。
() 匹配括號內的表示式,也表示一個組
2、匹配模式舉例
之前學過的字串的常用操作:一對一匹配
s1 = 'abcdefg你好' print(s1.find('你好')) # 7 返回的是字串開始的下標
2.1、單個匹配:
import re 1)、\w 和 \W 漢字字母數字下劃線 print(re.findall('\w', '你好[email protected]#$%^&*()-_=+')) # ['你', '好', 'T', 'o', 'm', '1', '2', '3', '_'] print(re.findall('\W', '你好[email protected]#$%^&*()-_=+')) # ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '=', '+'] 2)、 \s 和 \S 空格、TAB、換行符、回車 print(re.findall('\s','a 1\t\n\r')) # [' ', '\t', '\n', '\r'] print(re.findall('\S','a 1\t\n\r')) # ['a', '1'] 3)、\d 和 \D 數字 print(re.findall('\d','你好[email protected]#$%^&*()-_=+')) # ['1', '2', '3'] print(re.findall('\D','你好[email protected]#$%^&*()-_=+')) # ['你', '好', 'T', 'o', 'm', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '=', '+'] 4)、\A 和 ^ 以什麼開頭,字串寫在後面 print(re.findall('\Ahel','[email protected]#')) # ['hel'] print(re.findall('^hello','[email protected]#')) # ['hello'] 5)、\Z 和 $ 以什麼結尾,字串寫在前面 print(re.findall('@#\Z','[email protected]#')) # ['@#'] print(re.findall('[email protected]#$','[email protected]#')) # ['[email protected]#'] 6)、\n 和 \t \r print(re.findall('\n','h e l \n \t \r 123')) # ['\n'] print(re.findall('\t','h e l \n \t \r 123')) # ['\t'] print(re.findall('\r','h e l \n \t \r 123')) # ['\r']
2.2、重複匹配 . ? * + {m,n} .* .*?
import re # . 匹配任意字元,除了換行符(re.DOTALL這個引數可以匹配\n) print(re.findall('a.b','aab a b a1b a*b a.b a\nb')) # ['aab', 'a b', 'a1b', 'a*b', 'a.b'] print(re.findall('a.b','aab a b a1b a*b a.b a\nb',re.DOTALL)) # ['aab', 'a b', 'a1b', 'a*b', 'a.b', 'a\nb'] # ? 匹配0個或1個左邊字元 print(re.findall('a?b','aab aaab abb aabb')) # ['ab', 'ab', 'ab', 'b', 'ab', 'b'] # * 匹配0個或多個左邊字元,滿足貪婪匹配 print(re.findall('a*b','aab aaab abb aabb')) # ['aab', 'aaab', 'ab', 'b', 'aab', 'b'] # + 匹配1個或多個左邊字元,滿足貪婪匹配 print(re.findall('a+b','ab aab aaab abbb')) # ['ab', 'aab', 'aaab', 'ab'] # {m,n} 匹配m個至n個左邊字元,滿足貪婪匹配 print(re.findall('a{2,4}b','ab aab aaab aaaab aaaaab')) # ['aab', 'aaab', 'aaaab', 'aaaab'] # .* 匹配0個或多個任意非換行字元,貪婪匹配(從頭到尾匹配出來),加re.DOTALL就可以匹配換行符 print(re.findall('a.*b','ab aab a*()b a b a\nb')) # ['ab aab a*()b a b'] print(re.findall('a.*b','ab aab a*()b a b a\nb',re.DOTALL)) # ['ab aab a*()b a b a\nb'] # .*? 匹配0個或多個任意非換行字元,非貪婪匹配(一個一個匹配出來),加re.DOTALL就可以匹配換行符 #這裡的?不是0個或1個的意思,而是表示.*模式的非貪婪匹配,re.DOTALL可以匹配換行 print(re.findall('a.*?b','ab aab a*()b aaaab a b a\nb')) # ['ab', 'aab', 'a*()b', 'aaaab', 'a b'] # []: 括號中可以放任意一個字元,一箇中括號代表一個字元 # - 在[]中表示範圍,如果想要匹配上- 那麼這個-符號不能放在中間,只能放在兩邊 # ^ 在[]中表示取反的意思. print(re.findall('a.b', 'a1b a3b aeb a*b arb a_b')) # ['a1b', 'a3b', 'a4b', 'a*b', 'arb', 'a_b'] print(re.findall('a[abc]b', 'aab abb acb adb afb a_b')) # ['aab', 'abb', 'acb'] print(re.findall('a[0-9]b', 'a1b a3b aeb a*b arb a_b')) # ['a1b', 'a3b'] print(re.findall('a[a-z]b', 'a1b a3b aeb a*b arb a_b')) # ['aeb', 'arb'] print(re.findall('a[a-zA-Z]b', 'aAb aWb aeb a*b arb a_b')) # ['aAb', 'aWb', 'aeb', 'arb'] print(re.findall('a[0-9][0-9]b', 'a11b a12b a34b a*b arb a_b')) # ['a11b', 'a12b', 'a34b'] print(re.findall('a[*-+]b','a-b a*b a+b a/b a6b')) # ['a*b', 'a+b'] # - 在[]中表示範圍,如果想要匹配上- 那麼這個-符號不能放在中間. print(re.findall('a[-*+]b','a-b a*b a+b a/b a6b')) # ['a-b', 'a*b', 'a+b'] print(re.findall('a[^a-z]b', 'acb adb a3b a*b')) # ['a3b', 'a*b']
2.3、分組:
() 制定一個規則,將滿足規則的結果匹配出來 找到字串中'Tom_123 Mike_123 Jack_123'的 Tom、Mike、Jack print(re.findall('([a-zA-Z]+)_123','Tom_123 Mike_123 Jack_123')) 找出a標籤中的URL print(re.findall('href="(.*?)"','<a href="http://www.baidu.com">點選</a>'))#['http://www.baidu.com'] | 或匹配 print(re.findall('Tom|Mike|Jack', ' Tom123MikeaabJack')) # ['alex', '太白', 'wusir', '太白'] print(re.findall('compan(y|ies)','Too many companies have gone bankrupt, and the next one is my company')) # ['ies', 'y'] print(re.findall('compan(?:y|ies)','Too many companies have gone bankrupt, and the next one is my company')) # ['companies', 'company'] 分組() 中加入?: 表示將整體匹配出來而不只是()裡面的內容。
3、常用方法舉例
3.1、findall 全部找到返回一個列表。 print(re.findall('a', 'alexwusirbarryeval')) # ['a', 'a', 'a'] 3.2、search 只到找到第一個匹配然後返回一個包含匹配資訊的物件,該物件可以通過呼叫group()方法得到匹配的字串,如果字串沒有匹配,則返回None。 print(re.search('Tom|Mike', 'Mike and Tom are 18 years old')) # <_sre.SRE_Match object; span=(0, 4), match='Mike'> print(re.search('Tom|Mike', 'Mike and Tom are 18 years old').group()) # Mike 3.3、match 同search,不過在字串開始處進行匹配,完全可以用search+^代替match print(re.match('Tom|Mike', 'Mike and Tom are 18 years old')) # <_sre.SRE_Match object; span=(0, 4), match='Mike'> print(re.match('Tom|Mike', 'Mike and Tom are 18 years old').group()) # Mike 如果開頭沒有找到,則返回None print(re.match('Tom|Mike', '123 Mike and Tom are 18 years old')) #None 這時如果group()就會報錯 3.4、split 分割 可按照任意分割符進行分割 print(re.split('[ ::,;;,]','Tom:Mike:Jack,Rose;Bob;Lucy')) #['Tom', 'Mike', 'Jack', 'Rose', 'Bob', 'Lucy'] 3.5、sub 替換 print(re.sub('Tom', 'Mike', 'Tom is a student, Tom is 18 years old。')) # Mike is a student, Mike is 18 years old。 可以指定替換的次數 print(re.sub('Tom', 'Mike', 'Tom is a student, Tom is 18 years old。',1)) #Mike is a student, Tom is 18 years old。 也可以使用位置替換,將所有的字串按位置編號重新組合 print(re.sub('([a-zA-Z]+)([^a-zA-Z]+)([a-zA-Z]+)([^a-zA-Z]+)([a-zA-Z]+)([^a-zA-Z]+)([a-zA-Z]+)([^a-zA-Z]+)([a-zA-Z]+)', r'\5\2\3\4\1\6\7\8\9', r'Tom and Mike are friends')) # Mike and Tom are friends print(re.sub('([a-zA-Z]+)([^a-zA-Z]+)([a-zA-Z]+)([^a-zA-Z]+)([a-zA-Z]+)([^a-zA-Z]+)([a-zA-Z]+)([^a-zA-Z]+)([a-zA-Z]+)', r'\5\2\3\4\1', r'Tom and Mike are friends')) # Mike and Tom 3.6、compile表示式 obj=re.compile('\d{2}') print(obj.search('abc123eeee').group()) #12 print(obj.findall('abc123eeee')) #['12'],重用了obj 3.7、finditer 迭代器 ret = re.finditer('\d', 'ds3sy4784a') #finditer返回一個存放匹配結果的迭代器 print(ret) # <callable_iterator object at 0x10195f940> print(next(ret).group()) #檢視第一個結果 print(next(ret).group()) #檢視第二個結果 print([i.group() for i in ret]) #檢視剩餘的結果
4、命名分組舉例(瞭解)
命名分組匹配: ret = re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>") 還可以在分組中利用?<name>的形式給分組起名字 獲取的匹配結果可以直接用group('名字')拿到對應的值 print(ret.group('tag_name')) #結果 :h1 print(ret.group()) #結果 :<h1>hello</h1> ret = relx.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>") 如果不給組起名字,也可以用\序號來找到對應的組,表示要找的內容和前面的組內容一致 獲取的匹配結果可以直接用group(序號)拿到對應的值 print(ret.group(1)) print(ret.group()) #結果 :<h1>hello</h1>View Code
5、相關小練習
1、1-2*(60+(-40.35/5)-(-4*3))" 1.1 匹配所有的整數 print(re.findall('\d+',"1-2*(60+(-40.35/5)-(-4*3))")) # ['1', '2', '60', '40', '35', '5', '4', '3'] 1.2 匹配所有的數字(包含小數) print(re.findall(r'\d+\.?\d*|\d*\.?\d+', "1-2*(60+(-40.35/5)-(-4*3))")) # ['1', '2', '60', '40.35', '5', '4', '3'] 1.3 匹配所有的數字(包含小數包含負號) print(re.findall(r'-?\d+\.?\d*|\d*\.?\d+', "1-2*(60+(-40.35/5)-(-4*3))")) ['1', '-2', '60', '-40.35', '5', '-4', '3'] 2、匹配一段你文字中的每行的郵箱 http://blog.csdn.net/make164492212/article/details/51656638 匹配所有郵箱 例項1、只允許英文字母、數字、下劃線、英文句號、以及中劃線組成 舉例:zhangsan-001@gmail.com 分析郵件名稱部分: 26個大小寫英文字母表示為a-zA-Z 數字表示為0-9 下劃線表示為_ 中劃線表示為- 由於名稱是由若干個字母、數字、下劃線和中劃線組成,所以需要用到+表示多次出現 根據以上條件得出郵件名稱表示式:[a-zA-Z0-9_-]+ 分析域名部分: 一般域名的規律為“[N級域名][三級域名.]二級域名.頂級域名”,比如“qq.com”、“www.qq.com”、“mp.weixin.qq.com”、“12-34.com.cn”,分析可得域名類似“** .** .** .**”組成。 “**”部分可以表示為[a-zA-Z0-9_-]+ “.**”部分可以表示為\.[a-zA-Z0-9_-]+ 多個“.**”可以表示為(\.[a-zA-Z0-9_-]+)+ 綜上所述,域名部分可以表示為[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+ 最終表示式: 由於郵箱的基本格式為“名稱@域名”,需要使用“^”匹配郵箱的開始部分,用“$”匹配郵箱結束部分以保證郵箱前後不能有其他字元,所以最終郵箱的正則表示式為: ^[a-zA-Z0-9_-][email protected][a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$ 例項2、名稱允許漢字、字母、數字,域名只允許英文域名 舉例:楊元慶[email protected] 分析郵件名稱部分: 漢字在正則表示為[\u4e00-\u9fa5] 字母和數字表示為A-Za-z0-9 通過分析得出郵件名稱部分表示式為[A-Za-z0-9\u4e00-\u9fa5]+ 分析郵件域名部分 郵件部分可以參考例項1中的分析域名部分。 得出域名部分的表示式為[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+。 最終表示式: 我們用@符號將郵箱的名稱和域名拼接起來,因此完整的郵箱表示式為 ^[A-Za-z0-9\u4e00-\u9fa5][email protected][a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$ 3、匹配一段你文字中的每行的時間字串 這樣的形式:'1995-04-27' s1 = ''' 時間就是1980-01-02,2008-03-04 1980-01-02 is Tom's birthday Jack 1931-05-10:2010-10-20 2018-12-03 ''' print(re.findall('\d{4}-\d{2}-\d{2}', s1)) # ['1980-01-02', '2008-03-04', '1980-01-02', '1931-05-10', '2010-10-20', '2018-12-03'] 4、匹配 一個浮點數 print(re.findall('\d+\.\d*','1.17')) # ['1.17'] 5、匹配qq號:騰訊從10000開始: print(re.findall('[1-9][0-9]{4,}', '2413545136')) # ['2413545136'] 6、匹配標籤 s1 = ''' <p><a style="text-decoration: underline;" href="http://www.cnblogs.com/jin-xin/articles/7459977.html" target="_blank">python基礎一</a></p> <p><a style="text-decoration: underline;" href="http://www.cnblogs.com/jin-xin/articles/7562422.html" target="_blank">python基礎二</a></p> <p><a style="text-decoration: underline;" href="https://www.cnblogs.com/jin-xin/articles/9439483.html" target="_blank">Python最詳細,最深入的程式碼塊小資料池剖析</a></p> <p><a style="text-decoration: underline;" href="http://www.cnblogs.com/jin-xin/articles/7738630.html" target="_blank">python集合,深淺copy</a></p> <p><a style="text-decoration: underline;" href="http://www.cnblogs.com/jin-xin/articles/8183203.html" target="_blank">python檔案操作</a></p> <h4 style="background-color: #f08080;">python函式部分</h4> <p><a style="text-decoration: underline;" href="http://www.cnblogs.com/jin-xin/articles/8241942.html" target="_blank">python函式初識</a></p> <p><a style="text-decoration: underline;" href="http://www.cnblogs.com/jin-xin/articles/8259929.html" target="_blank">python函式進階</a></p> <p><a style="text-decoration: underline;" href="http://www.cnblogs.com/jin-xin/articles/8305011.html" target="_blank">python裝飾器</a></p> <p><a style="text-decoration: underline;" href="http://www.cnblogs.com/jin-xin/articles/8423526.html" target="_blank">python迭代器,生成器</a></p> <p><a style="text-decoration: underline;" href="http://www.cnblogs.com/jin-xin/articles/8423937.html" target="_blank">python內建函式,匿名函式</a></p> <p><a style="text-decoration: underline;" href="http://www.cnblogs.com/jin-xin/articles/8743408.html" target="_blank">python遞迴函式</a></p> <p><a style="text-decoration: underline;" href="https://www.cnblogs.com/jin-xin/articles/8743595.html" target="_blank">python二分查詢演算法</a></p> ''' 6.1、找到所有的p標籤 ret = re.findall('<p>.*?</p>', s1) print(ret) 6.2、找到所有a標籤對應的url print(re.findall('<a.*?href="(.*?)".*?</a>',s1)) print(re.findall('href="(.*?)"', s1))View Code