引言
文本處理已經(jīng)成為計(jì)算機(jī)常見工作之一,?對(duì)文本的搜索、定位、提取的邏輯往往比較復(fù)雜,?為了解決上述問題,產(chǎn)生正則表達(dá)式技術(shù)
正則表達(dá)式即文本的高級(jí)匹配模式,提供搜索,替代,獲取等功能。本質(zhì)是由一系列特殊符號(hào)和字符構(gòu)成的自串,這個(gè)自串就是正則表達(dá)式。
正則表達(dá)式能夠方便地進(jìn)行檢索和修改等文本操作;靈活多樣;支持語言眾多;
正則表達(dá)式匹配手段:通過設(shè)定有特殊意義的符號(hào),描述符號(hào)和字符的重復(fù)行為及位置特征來表示一類特定規(guī)則的字符串
import re
re.findall(pattern, string)
參數(shù):
* pattern: 以字符串的形式傳入一個(gè)正則表達(dá)式
* string:要匹配的目標(biāo)字符串
返回值:
* 得到一個(gè)列表,將目標(biāo)子串中能用正則表達(dá)式匹配的內(nèi)容放入列表
元字符的使用
普通字符?
匹配規(guī)則:每個(gè)普通字符匹配其對(duì)應(yīng)的字符
re.findall('ab',"abcdefabcd") # ['ab', 'ab']
或
元字符:? |
匹配規(guī)則:匹配 | 兩側(cè)的正則表達(dá)式
re.findall('com|cn',"www.baidu.com/www.tmooc.cn") # ['com', 'cn']
匹配單個(gè)字符
元字符: .
匹配規(guī)則:匹配除 \n外任意一個(gè)字符
re.findall('張.豐',"張三豐,張四豐,張五豐") # ['張三豐', '張四豐', '張五豐']
匹配字符集
元字符: [字符集]
匹配規(guī)則: 匹配字符集中的任意一個(gè)字符
表達(dá)形式:
* [abc#!好] 表示 [ ] 中的任意一個(gè)字符
* [0-9], [a-z], [A-Z] 表示區(qū)間內(nèi)的任意一個(gè)字符
* [_#?0-9a-z] 混合書寫,一般區(qū)間表達(dá)寫在后面 re.findall('[aeiou]',"How are you!") # ['o',
'a', 'e', 'o', 'u']
匹配字符集反集
元字符: [^字符集]
匹配規(guī)則: 匹配除了字符集以外的任意一個(gè)字符
re.findall('[^0-9]',"Use 007 port") # ['U', 's', 'e', ' ', ' ', 'p', 'o', 'r',
't']
匹配開始位置
* 元字符:? ^
* 匹配規(guī)則: 匹配目標(biāo)字符串的開頭位置 re.findall('^Jame',"Jame,hello") # ['Jame']
匹配結(jié)束位置
* 元字符:$
* 匹配規(guī)則:匹配目標(biāo)字符串的結(jié)束位置 re.findall('Jame$',"Hi,Jame") # ['Jame']
* 規(guī)則技巧:? ^ 和 $必然出現(xiàn)在正則表達(dá)式的開頭和結(jié)尾處。如果兩者同時(shí)出現(xiàn),則中間的部分必須匹配整個(gè)目標(biāo)字符串的全部?jī)?nèi)容。
匹配字符重復(fù)
* 元字符:? *
* 匹配規(guī)則: 匹配前面的字符出現(xiàn)0次或多次 re.findall("wo*", "woooo~~w!") # w后面o出現(xiàn)多次的情況和出現(xiàn)0次的情況 #
['woooo', 'w'] # 大寫字母后面跟小寫之母出現(xiàn)0次或多次 re.findall("[A-Z][a-z]*", "How ary you?
Finf Ha") # ['How', 'Finf', 'Ha']
* 元字符: +
* 匹配規(guī)則: 匹配前面的字符出現(xiàn)后面的字符的次數(shù)1次或多次的情況 # 大寫之母后面跟小寫之母出現(xiàn)1次或多次 re.findall('[A-Z][a-z]+
',"Hello World") # ['Hello', 'World']
* 元字符: ?
* 匹配規(guī)則: 匹配前面的字符出現(xiàn)0次或1次 # 匹配整數(shù) re.findall('-?[0-9]+',"Jame,age:18, -26") #
['18', '-26']
* 元字符: {n}
* 匹配規(guī)則: 匹配前面的字符出現(xiàn)n次 # 匹配手機(jī)號(hào)碼 re.findall('1[0-9]{10}',"Jame:13886495728") #
['13886495728']
* 元字符: {m,n}
* 匹配規(guī)則: 匹配前面的字符出現(xiàn) [m-n] 次 # 匹配qq號(hào) re.findall('[1-9][0-9]{5,10}',"
Baron:1259296994") # ['1259296994']
匹配任意(非)數(shù)字字符
* 元字符: \d \D
* 匹配規(guī)則: \d 匹配任意數(shù)字字符, \D 匹配任意非數(shù)字字符 # 匹配端口 re.findall('\d{1,5}',"Mysql: 3306,
http:80") # ['3306', '80']?
匹配任意(非)普通字符
* 元字符: \w? \W
* 匹配規(guī)則: \w 匹配普通字符, \W 匹配非普通字符
* 說明: 普通字符指?數(shù)字,?字母,?下劃線,?漢字。 re.findall('\w+',"server_port = 8888") #
['server_port', '8888']
匹配任意(非)空字符
* 元字符: \s \S
* 匹配規(guī)則: \s 匹配空字符, \S 匹配非空字符
* 說明:空字符指 空格 \r \n \t \v \f 字符 re.findall('\w+\s+\w+',"hello world") #
['hello world']
匹配開頭結(jié)尾位置
* 元字符: \A \Z
* 匹配規(guī)則: \A 表示開頭位置, \Z 表示結(jié)尾位置 re.findall("\Ahello","hello world") # ['hello']
re.findall("world\Z","hello world") # ['world']
匹配(非)單詞的邊界位置
* 元字符: \b \B
* 匹配規(guī)則: \b 表示單詞邊界, \B 表示非單詞邊界
* 說明:單詞邊界指數(shù)字字母(漢字)下劃線與其他字符的交界位置。 re.findall(r'\bis\b',"This is a test.") #
['is']
總結(jié):
類別 元字符
匹配字符 . [...] [^...] \d \D \w \W \s \S
匹配重復(fù) * + ? {n} {m,n}
匹配位置 ^ $ \A \Z \b \B
其他 | () \
正則表達(dá)式的轉(zhuǎn)義
1. 如果使用正則表達(dá)式匹配特殊字符則需要加 \ 表示轉(zhuǎn)義。
特殊字符: . * + ? ^ $ [] () {} | \
# 匹配特殊字符 . 時(shí)使用 \. 表示本身含義 re.findall('-?\d+\.?\d*',"123,-123,1.23,-1.23") #
['123', '-123', '1.23', '-1.23']
2. 在編程語言中,常使用原生字符串書寫正則表達(dá)式避免多重轉(zhuǎn)義的麻煩。
python字符串? -->?正則 --> 目標(biāo)字符串
"\\$\\d+"??解析為??\$\d+ 匹配 "$100"
"\\$\\d+"??等同于??r"\$\d+"
貪婪模式和非貪婪模式
貪婪模式: 默認(rèn)情況下,匹配重復(fù)的元字符總是盡可能多的向后匹配內(nèi)容。比如: * + ? {m,n}
非貪婪模式(懶惰模式): 讓匹配重復(fù)的元字符盡可能少的向后匹配內(nèi)容。
貪婪模式轉(zhuǎn)換為非貪婪模式:?在匹配重復(fù)元字符后加? '?'? 號(hào)即可
* ---> *? ;? ? ? ? ?+ ---> +? ;? ? ? ?? ---> ?? {m,n} ---> {m,n}?
re.findall("ab*", "abbbbb") # ['abbbbb'] re.findall("ab*?", "abbbbb") # ['a']
re.findall("ab+", "abbbbb") # ['abbbbb'] re.findall("ab+?", "abbbbb") # ['ab']
練習(xí)"
# 把數(shù)字匹配出來 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'] # 匹配一個(gè).com郵箱格式字符串 print(re.findall(r"\w+@\w+", "
[email protected]")) # 匹配一個(gè)密碼 8-12位數(shù)字字母下劃線構(gòu)成 print(re.findall(r"\w{8,12}", "
Tedu023256")) # 匹配一個(gè)數(shù)字 正數(shù),負(fù)數(shù),整數(shù),小數(shù),分?jǐn)?shù)1/2,百分?jǐn)?shù)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"))
分組
在正則表達(dá)式中, 以 () 建立正則表達(dá)式的內(nèi)部分組, 匹配括號(hào)內(nèi)的表達(dá)式,分組的作用是在完整的模式中定義子模型,將每個(gè)圓括號(hào)中子模式專門匹配出來。
* 可以被作為整體操作, 改變?cè)址牟僮鲗?duì)象 # 改變 +號(hào) 重復(fù)的對(duì)象 re.search(r'(ab)+',"ababababab").group()
# 'ababababab' # 改變 |號(hào) 操作對(duì)象 re.search(r'(王|李)\w{1,3}',"王者榮耀").group() # '王者榮耀'
* ?可以通過編程語言某些接口獲取匹配內(nèi)容中,子組對(duì)應(yīng)的內(nèi)容部分? # 獲取url協(xié)議類型 re.search(r'
(https|http|ftp|file)://\S+',"https://www.baidu.com").group(1) # 'https'
?先匹配外部正則,再進(jìn)一步匹配括號(hào)中的正則
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) View Code
分組總結(jié)
* 在網(wǎng)頁中,想要什么內(nèi)容,就加?( )
* 先按整體正則匹配,然后再提取分組()中的內(nèi)容 ?
* 如果有2個(gè)及以上分組(),則結(jié)果中以元組形式顯示 [(),(),()]
捕獲組
可以給正則表達(dá)式的子組起一個(gè)名字,表達(dá)該子組的意義。這種有名稱的子組即為捕獲組。
格式: (?P<name>pattern)
# 給子組命名為 "pig" re.search(r'(?P<pig>ab)+',"ababababab").group('pig') # 'ab'
注意事項(xiàng)
* 一個(gè)正則表達(dá)式中可以包含多個(gè)子組
* 子組可以嵌套,但是不要重疊或者嵌套結(jié)構(gòu)復(fù)雜
* 子組序列號(hào)一般從外到內(nèi),從左到右計(jì)數(shù)
Python re模塊
re.match函數(shù)
re.match(pattern, string, flags=0)
參數(shù):
* pattern 正則
* string 目標(biāo)字符串
* flags 標(biāo)志位
<https://www.runoob.com/python3/python3-reg-expressions.html#flags>,
用于控制表達(dá)式的匹配方式,如:是否區(qū)分大小寫...
返回值:匹配內(nèi)容match 對(duì)象
re.match嘗試從字符串的起始位置匹配一個(gè)模型,如果不是起始位置匹配成功的話,match()就返回none.
import re print(re.match('www', 'www.runoob.com').span()) # 在起始位置匹配, (0, 3)
print(re.match('com', 'www.runoob.com')) # 不在起始位置匹配, None
我們可以使用group()或groups()匹配對(duì)象函數(shù)來匹配表達(dá)式.?
* group(num=0) 匹配的整個(gè)表達(dá)式的字符串,group() 可以一次輸入多個(gè)組號(hào),在這種情況下它將返回一個(gè)包含那些組所對(duì)應(yīng)值的元組。
* groups()? ? ? ? ? ? ? ? 返回一個(gè)包含所有小組字符串的元組,從 1 到 所含的小組號(hào)。 import re line = "
Cats are smarter than dogs" # .* 表示任意匹配除換行符(\n、\r)之外的任何單個(gè)或多個(gè)字符 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函數(shù)
re.search 掃描整個(gè)字符串并返回第一個(gè)成功的匹配。
re.search(pattern, string, flags=0)
參數(shù):
* pattern 正則
* string 目標(biāo)字符串
* flags 標(biāo)志位
<https://www.runoob.com/python3/python3-reg-expressions.html#flags>,
用于控制表達(dá)式的匹配方式,如:是否區(qū)分大小寫...
返回值: 匹配目標(biāo)字符串第一個(gè)符合內(nèi)容 的對(duì)象
我們可以使用group(num) 或 groups() 匹配對(duì)象函數(shù)來獲取匹配表達(dá)式。同re.match
import re line = "Cats are smarter than dogs" # .*
表示任意匹配除換行符(\n、\r)之外的任何單個(gè)或多個(gè)字符 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區(qū)別:
re.match只匹配字符串的開始,如果字符串開始不符合正則表達(dá)式,則匹配失敗,函數(shù)返回None;而re.search匹配整個(gè)字符串,直到找到一個(gè)匹配。
re.sub()替換函數(shù)
re.sub(pattern,replace,string,max,flags = 0)
使用一個(gè)字符串替換正則表達(dá)式匹配到的內(nèi)容
參數(shù):
* pattern 正則表達(dá)式
* replace 替換的字符串
* string 目標(biāo)字符串
* max?最多替換幾處, 默認(rèn)替換全部
* flags 功能標(biāo)志位,擴(kuò)展正則表達(dá)式的匹配
返回值: 替換后的字符串
import re phone = "2004-959-559 # 這是一個(gè)電話號(hào)碼" # 刪除注釋 num_1 = re.sub(r'#.*$', "",
phone)# 2004-959-559 # 移除非數(shù)字的內(nèi)容 num_2 = re.sub(r'\D', "", phone) # 2004959559 #
替換匹配到的內(nèi)容 s = re.subn(r'\s+', '#', "This is a test", 2) # ('This#is#a test', 2)
compile 函數(shù)
regex = compile(pattern,flags = 0)
參數(shù):
* pattern 正則表達(dá)式
* flags 功能標(biāo)志位,擴(kuò)展正則表達(dá)式的匹配
返回值:? 正則表達(dá)式對(duì)象
compile 函數(shù)用于編譯正則表達(dá)式,生成一個(gè)正則表達(dá)式( Pattern )對(duì)象,供 match() 和 search() 這兩個(gè)函數(shù)使用。
import re pattern = re.compile(r'([a-z]+) ([a-z]+)', re.I) # re.I 表示忽略大小寫 m =
pattern.match('Hello World Wide Web') print(m) # 匹配成功,返回一個(gè) Match 對(duì)象 #
<_sre.SRE_Match object; span=(0, 11), match='Hello World'> print(m.group(0)) #
返回匹配成功的整個(gè)子串,Hello World print(m.group(1)) # 返回第一個(gè)分組匹配成功的子串,Hello print
(m.groups())# 等價(jià)于 (m.group(1), m.group(2), ...) ('Hello', 'World') print
(m.group(3))# 不存在第三個(gè)分組 報(bào)錯(cuò)!!! print(m.span(0)) # 返回匹配成功的整個(gè)子串的索引,(0, 11)
re.findall()函數(shù)?
re.findall(pattern,string,flags = 0)
參數(shù):
* pattern 正則表達(dá)式
* string 目標(biāo)字符串
* flags 功能標(biāo)志位,擴(kuò)展正則表達(dá)式的匹配
返回值:?在字符串中找到正則表達(dá)式所匹配的所有子串,并返回一個(gè)列表,如果沒有找到匹配的,則返回空列表。
注意:?match 和 search 是匹配一次 findall 匹配所有。
import re # 目標(biāo)字符串 s = "Alex:1994,Sunny:1993" pattern = r"(\w+):(\d+)" #
re模塊調(diào)用findall l = re.findall(pattern, s) print(l) # [('Alex', '1994'),
('Sunny', '1993')]
?
re.finditer(pattern,string,flags = 0) 根據(jù)正則表達(dá)式匹配目標(biāo)字符串內(nèi)容
參數(shù):
* pattern 正則表達(dá)式
* string 目標(biāo)字符串
* flags 功能標(biāo)志位,擴(kuò)展正則表達(dá)式的匹配
返回值: 匹配結(jié)果的迭代器, 返回的對(duì)象要通過.group()取值
import re s = "2019年,建國70年" pattern = r'\d+' # 返回迭代器 it =
re.finditer(pattern,s)for i in it: print(i) # 獲取match對(duì)象對(duì)應(yīng)內(nèi)容 # <_sre.SRE_Match
object; span=(0, 4), match='2019'> # <_sre.SRE_Match object; span=(0, 4),
match='70'>
re.fullmatch(pattern,string,flags=0)
參數(shù):
* pattern 正則
* string 目標(biāo)字符串
返回值:完全匹配某個(gè)目標(biāo)字符串 object
# 完全匹配 print(re.fullmatch("[,\w]+", s).group()) # 2019年,建國70年
re.split(pattern,string,flags = 0) 使用正則表達(dá)式匹配內(nèi)容,切割目標(biāo)字符串
參數(shù):
* pattern 正則表達(dá)式
* string 目標(biāo)字符串
* flags 功能標(biāo)志位,擴(kuò)展正則表達(dá)式的匹配
返回值: 切割后的內(nèi)容列表
s = "Alex:1994,Sunny:1993" # 按照匹配內(nèi)容切割字符串 l = re.split(r'[:,]', s) print(l) #
['Alex', '1994', 'Sunny', '1993']
?
熱門工具 換一換