文本處理已經成爲計算機常見工做之一, 對文本的搜索、定位、提取的邏輯每每比較複雜, 爲了解決上述問題,產生正則表達式技術html
正則表達式即文本的高級匹配模式,提供搜索,替代,獲取等功能。本質是由一系列特殊符號和字符構成的自串,這個自串就是正則表達式。python
正則表達式可以方便地進行檢索和修改等文本操做;靈活多樣;支持語言衆多;正則表達式
正則表達式匹配手段:經過設定有特殊意義的符號,描述符號和字符的重複行爲及位置特徵來表示一類特定規則的字符串sql
import reexpress
re.findall(pattern, string)編程
參數:c#
返回值:編程語言
匹配規則:每一個普通字符匹配其對應的字符ide
re.findall('ab',"abcdefabcd") # ['ab', 'ab']
元字符: |函數
匹配規則:匹配 | 兩側的正則表達式
re.findall('com|cn',"www.baidu.com/www.tmooc.cn") # ['com', 'cn']
元字符: .
匹配規則:匹配除 \n外任意一個字符
re.findall('張.豐',"張三丰,張四豐,張五豐") # ['張三丰', '張四豐', '張五豐']
元字符: [字符集]
匹配規則: 匹配字符集中的任意一個字符
表達形式:
re.findall('[aeiou]',"How are you!") # ['o', 'a', 'e', 'o', 'u']
元字符: [^字符集]
匹配規則: 匹配除了字符集之外的任意一個字符
re.findall('[^0-9]',"Use 007 port") # ['U', 's', 'e', ' ', ' ', 'p', 'o', 'r', 't']
re.findall('^Jame',"Jame,hello") # ['Jame']
re.findall('Jame$',"Hi,Jame") # ['Jame']
re.findall("wo*", "woooo~~w!") # w後面o出現屢次的狀況和出現0次的狀況 # ['woooo', 'w']
# 大寫字母后面跟小寫之母出現0次或屢次 re.findall("[A-Z][a-z]*", "How ary you? Finf Ha") # ['How', 'Finf', 'Ha']
# 大寫之母后面跟小寫之母出現1次或屢次 re.findall('[A-Z][a-z]+',"Hello World") # ['Hello', 'World']
# 匹配整數 re.findall('-?[0-9]+',"Jame,age:18, -26") # ['18', '-26']
# 匹配手機號碼 re.findall('1[0-9]{10}',"Jame:13886495728") # ['13886495728']
# 匹配qq號 re.findall('[1-9][0-9]{5,10}',"Baron:1259296994") # ['1259296994']
# 匹配端口 re.findall('\d{1,5}',"Mysql: 3306, http:80") # ['3306', '80']
re.findall('\w+',"server_port = 8888") # ['server_port', '8888']
re.findall('\w+\s+\w+',"hello world") # ['hello world']
re.findall("\Ahello","hello world") # ['hello'] re.findall("world\Z","hello world") # ['world']
re.findall(r'\bis\b',"This is a test.") # ['is']
總結:
類別 | 元字符 |
匹配字符 | . [...] [^...] \d \D \w \W \s \S |
匹配重複 | * + ? {n} {m,n} |
匹配位置 | ^ $ \A \Z \b \B |
其餘 | | () \ |
正則表達式的轉義
1. 若是使用正則表達式匹配特殊字符則須要加 \ 表示轉義。
特殊字符: . * + ? ^ $ [] () {} | \
# 匹配特殊字符 . 時使用 \. 表示自己含義 re.findall('-?\d+\.?\d*',"123,-123,1.23,-1.23") # ['123', '-123', '1.23', '-1.23']
2. 在編程語言中,常使用原生字符串書寫正則表達式避免多重轉義的麻煩。
python字符串 --> 正則 --> 目標字符串
"\\$\\d+" 解析爲 \$\d+ 匹配 "$100"
"\\$\\d+" 等同於 r"\$\d+"
貪婪模式: 默認狀況下,匹配重複的元字符老是儘量多的向後匹配內容。好比: * + ? {m,n}
非貪婪模式(懶惰模式): 讓匹配重複的元字符儘量少的向後匹配內容。
貪婪模式轉換爲非貪婪模式: 在匹配重複元字符後加 '?' 號便可
* ---> *? ; + ---> +? ; ? ---> ?? {m,n} ---> {m,n}?
re.findall("ab*", "abbbbb") # ['abbbbb'] re.findall("ab*?", "abbbbb") # ['a'] re.findall("ab+", "abbbbb") # ['abbbbb'] re.findall("ab+?", "abbbbb") # ['ab']
練習"
# 把數字匹配出來 re.findall("[^ ]+", "12 -36 28 1.34 -3.8") # ['12', '-36', '28', '1.34', '-3.8'] re.findall("-?\d+\.?\d*", "12 -36 28 1.34 -3.8") # ['12', '-36', '28', '1.34', '-3.8']
# 匹配一個.com郵箱格式字符串 print(re.findall(r"\w+@\w+", "lvze@163.com")) # 匹配一個密碼 8-12位數字字母下劃線構成 print(re.findall(r"\w{8,12}", "Tedu023256")) # 匹配一個數字 正數,負數,整數,小數,分數1/2,百分數45% print(re.findall(r"-?\d+/?\.?\d*%?", "12 -3 3.5 5.45 42% 1/3")) # 匹配一段文字中以大寫字母開頭的單詞,注意文字中可能有ipython(不算)H-base(算),單詞可能有大寫字母小寫之母 -_ print(re.findall(r"\b[A-Z][-_a-zA-Z]*", "Hello ipython H-base BSD"))
在正則表達式中, 以 () 創建正則表達式的內部分組, 匹配括號內的表達式,分組的做用是在完整的模式中定義子模型,將每一個圓括號中子模式專門匹配出來。
# 改變 +號 重複的對象 re.search(r'(ab)+',"ababababab").group() # 'ababababab' # 改變 |號 操做對象 re.search(r'(王|李)\w{1,3}',"王者榮耀").group() # '王者榮耀'
# 獲取url協議類型 re.search(r'(https|http|ftp|file)://\S+',"https://www.baidu.com").group(1) # 'https'
先匹配外部正則,再進一步匹配括號中的正則
import re s = 'A B C D' p1 = re.compile('\w+\s+\w+') print(p1.findall(s)) # # ['A B','C D'] p2 = re.compile('(\w+)\s+\w+') print(p2.findall(s)) # # ['A','C'] p3 = re.compile('(\w+)\s+(\w+)') print(p3.findall(s)) # # [('A','B'),('C','D')]
import re html = '''<div class="animal"> <p class="name"> <a title="Tiger"></a> </p> <p class="content"> Two tigers two tigers run fast </p> </div> <div class="animal"> <p class="name"> <a title="Rabbit"></a> </p> <p class="content"> Small white rabbit white and white </p> </div>''' pattern = re.compile( '<div class="animal">.*?title="(.*?)".*?' 'class="content">(.*?)</p>', re.S) r_list = pattern.findall(html) print(r_list)
分組總結
捕獲組
能夠給正則表達式的子組起一個名字,表達該子組的意義。這種有名稱的子組即爲捕獲組。
格式: (?P<name>pattern)
# 給子組命名爲 "pig" re.search(r'(?P<pig>ab)+',"ababababab").group('pig') # 'ab'
注意事項
re.match(pattern, string, flags=0)
參數:
返回值:匹配內容match 對象
re.match嘗試從字符串的起始位置匹配一個模型,若是不是起始位置匹配成功的話,match()就返回none.
import re print(re.match('www', 'www.runoob.com').span()) # 在起始位置匹配, (0, 3) print(re.match('com', 'www.runoob.com')) # 不在起始位置匹配, None
咱們可使用group()或groups()匹配對象函數來匹配表達式.
import re line = "Cats are smarter than dogs" # .* 表示任意匹配除換行符(\n、\r)以外的任何單個或多個字符 matchObj = re.match(r'(.*) are (.*?) .*', line) print(matchObj.group()) # Cats are smarter than dogs print(matchObj.group(1)) # Cats print(matchObj.group(2)) # smarter m = re.match(r"[A-Z]\w*", "Hello World") print(m.group()) # Hello
re.search 掃描整個字符串並返回第一個成功的匹配。
re.search(pattern, string, flags=0)
參數:
返回值: 匹配目標字符串第一個符合內容 的對象
咱們可使用group(num) 或 groups() 匹配對象函數來獲取匹配表達式。同re.match
import re line = "Cats are smarter than dogs" # .* 表示任意匹配除換行符(\n、\r)以外的任何單個或多個字符 searchObj = re.search(r'(.*) are (.*?) .*', line) print(searchObj) # <_sre.SRE_Match object; span=(0, 26), match='Cats are smarter than dogs'> print(searchObj.group()) # Cats are smarter than dogs print(searchObj.group(1)) # Cats print(searchObj.group(2)) # smarter # 匹配第一處 m = re.search(r"[A-Z]\w*", " Hello World") print(m.group()) # Hello
match和search區別: re.match只匹配字符串的開始,若是字符串開始不符合正則表達式,則匹配失敗,函數返回None;而re.search匹配整個字符串,直到找到一個匹配。
re.sub(pattern,replace,string,max,flags = 0)
使用一個字符串替換正則表達式匹配到的內容
參數:
返回值: 替換後的字符串
import re phone = "2004-959-559 # 這是一個電話號碼" # 刪除註釋 num_1 = re.sub(r'#.*$', "", phone) # 2004-959-559 # 移除非數字的內容 num_2 = re.sub(r'\D', "", phone) # 2004959559 # 替換匹配到的內容 s = re.subn(r'\s+', '#', "This is a test", 2) # ('This#is#a test', 2)
regex = compile(pattern,flags = 0)
參數:
返回值: 正則表達式對象
compile 函數用於編譯正則表達式,生成一個正則表達式( Pattern )對象,供 match() 和 search() 這兩個函數使用。
import re pattern = re.compile(r'([a-z]+) ([a-z]+)', re.I) # re.I 表示忽略大小寫 m = pattern.match('Hello World Wide Web') print(m) # 匹配成功,返回一個 Match 對象 # <_sre.SRE_Match object; span=(0, 11), match='Hello World'> print(m.group(0)) # 返回匹配成功的整個子串,Hello World print(m.group(1)) # 返回第一個分組匹配成功的子串,Hello print(m.groups()) # 等價於 (m.group(1), m.group(2), ...) ('Hello', 'World') print(m.group(3)) # 不存在第三個分組 報錯!!! print(m.span(0)) # 返回匹配成功的整個子串的索引,(0, 11)
re.findall(pattern,string,flags = 0)
參數:
返回值: 在字符串中找到正則表達式所匹配的全部子串,並返回一個列表,若是沒有找到匹配的,則返回空列表。
注意: match 和 search 是匹配一次 findall 匹配全部。
import re # 目標字符串 s = "Alex:1994,Sunny:1993" pattern = r"(\w+):(\d+)" # re模塊調用findall l = re.findall(pattern, s) print(l) # [('Alex', '1994'), ('Sunny', '1993')]
re.finditer(pattern,string,flags = 0) 根據正則表達式匹配目標字符串內容
參數:
返回值: 匹配結果的迭代器, 返回的對象要經過.group()取值
import re s = "2019年,建國70年" pattern = r'\d+' # 返回迭代器 it = re.finditer(pattern,s) for i in it: print(i) # 獲取match對象對應內容 # <_sre.SRE_Match object; span=(0, 4), match='2019'> # <_sre.SRE_Match object; span=(0, 4), match='70'>
re.fullmatch(pattern,string,flags=0)
參數:
返回值:徹底匹配某個目標字符串 object
# 徹底匹配 print(re.fullmatch("[,\w]+", s).group()) # 2019年,建國70年
re.split(pattern,string,flags = 0) 使用正則表達式匹配內容,切割目標字符串
參數:
返回值: 切割後的內容列表
s = "Alex:1994,Sunny:1993" # 按照匹配內容切割字符串 l = re.split(r'[:,]', s) print(l) # ['Alex', '1994', 'Sunny', '1993']