Python的正则表达式和re模块
1. 正則表達(dá)式
1.1 用處
正則表達(dá)式就是記錄文本規(guī)則的代碼
這句話我覺(jué)得概括的很精煉.
1.2 元字符
正則表達(dá)式里有一些元字符, 他們代表的是很多意思, 有某種特征的集合呀, 不包括某種字符的集合呀.
1.2.1 匹配字符種類的元字符
以下探討的都是代表一個(gè)字符的元字符.
. : 就是英文字符的句號(hào) . , 匹配除了換行符以外的任意字符。
\s: 匹配任意的空白符,包括空格,制表符(Tab),換行符,中文全角空格等.
\S: 匹配任意不是空白符的字符.
\w: 匹配字母[a-z], [A-Z] 或數(shù)字[0-9] 或下劃線_ 或漢字等.
\W: 匹配任意不是字母,數(shù)字,下劃線,漢字的字符.
\d: 是匹配一位數(shù)字從0到9, 任意一個(gè)數(shù)字就行。
\D: 匹配任意非數(shù)字的字符
\b: 并不匹配這些單詞分隔字符中的任何一個(gè),它只匹配一個(gè)位置. 這個(gè)位置和后一個(gè)字符或者前一個(gè)字符的類型不一樣.
比如: \b\w, 這個(gè)\b就是匹配不是\w的字符, 并且不會(huì)匹配到這個(gè)字符; 如果是\b. , 就是匹配不是. 的字符. 就近匹配,比如\bAB 匹配A,AB\b 匹配B
\B: 就是上面反過(guò)來(lái), 說(shuō)不清, 舉例來(lái)看: ‘a(chǎn)abbc’ 中 ‘\Ba’ 匹配的是第二個(gè)a, 因?yàn)閈B代表跟后面的字符類型一樣的字符, 但是不要這個(gè)\B代表的字符.
[ ]:從中挑一個(gè)字符, 注意是一個(gè)字符, 例如[fuck]就是從f, u, c, k 四個(gè)字符中挑選一個(gè), 還有[0-9]從0到9選一個(gè), 還有[a-d]或者[E-G], 從a, b, c, d 或者E, F, G中選一個(gè).
| : 從前或者后, 選出取個(gè)來(lái), 是或的意思. 例如: ‘a(chǎn)bc|de’ 的符合匹配對(duì)象是’abc’ 或者’de’, 而不是’abc’ 或’abde’. 一定要注意.
[^ ]: 取反^配合[ ]使用, 就是[ ]內(nèi)的字符以外的字符都可以, 例如: [^\d]匹配除了數(shù)字以外的任意字符, [^aeiou]匹配除了aeiou這幾個(gè)字母以外的任意字符.
\A: 代表后面這個(gè)字符必須在字符串開(kāi)頭. 例如: ‘a(chǎn)ba’ 用’\Aa’ 來(lái)匹配, 能匹配到第一個(gè)a, 不能匹配到第二個(gè)a; 如果用’\Ab’ 來(lái)匹配, 匹配不到.
^: 用來(lái)表示, ^后面這個(gè)字符, 必須是一行的開(kāi)始, mutilline模式下, 會(huì)按行分隔符分隔成很多行, 所以會(huì)有很多行首, 在默認(rèn)模式和singleline模式下, 就是一個(gè)長(zhǎng)的字符串, 所以只有一個(gè)行首
$: $前面的這個(gè)字符, 必須是行尾, 規(guī)律同上.
一共11種.
1.2.2 控制字符數(shù)量的元字符
配合上面代表字符種類的元字符使用, 接在字符的后面, 可以代表字符重復(fù)多少次. 注意, 他們只控制前面一個(gè)字符的數(shù)量.
貪婪地匹配:
因?yàn)槟芷ヅ涞降臄?shù)量不確定, 所以就盡可能多的匹配, 比如’@bbb@bbb@’ 中, 用’@.+@’來(lái)匹配, 結(jié)果是’@bbb@bbb@’ .
* :前邊的內(nèi)容可以連續(xù)重復(fù)使用任意次以使整個(gè)表達(dá)式得到匹配。.* 連在一起, 在singleline模式下就意味著任意數(shù)量的不包含換行的字符。
+: 重復(fù)一次以上
?: 重復(fù)零次或一次
{n}: 重復(fù)n次
{n,}: 重復(fù)n次或更多次, {1,} 相當(dāng)于+ .
{n,m}: 重復(fù)n到m次, {0,1} 相當(dāng)于? . 例如: 0\d{2}-\d{8}。這里\d后面的{2}({8})的意思是前面\d必須連續(xù)重復(fù)匹配2次(8次), 用于匹配0xx-xxxxxxxx這樣的字符串.
有時(shí)候, 我們需要這些元字符的本意, 比如我就想查找?, 這是需要用\來(lái)取消這些字符的特殊意義, \?就表示?。所以要查找\本身,要用\.
正則表達(dá)式里的分枝條件指的是有幾種規(guī)則,只要滿足這些規(guī)則中的任意一種,都會(huì)被當(dāng)成匹配,因此我們要使用 | 把這些規(guī)則分開(kāi)。
懶惰地匹配:
還是上面那個(gè)例子, 如果只想要’@bbb@bbb@’ 中, 符合條件的第一個(gè)字符串, 就可以用’@.+?@’來(lái)匹配, 結(jié)果是’@bbb@’, 是左邊的那個(gè) .
*?: 重復(fù)任意次,但盡可能少重復(fù)
+?: 重復(fù)1次或更多次,但盡可能少重復(fù)
??: 重復(fù)0次或1次,但盡可能少重復(fù)
{n,m}?: 重復(fù)n到m次,但盡可能少重復(fù)
{n,}?: 重復(fù)n次以上,但盡可能少重復(fù)
1.2.3 匹配重復(fù)出現(xiàn)某一組成部分的字符串
有的時(shí)候, 我們要用到前面匹配的字符串, 但是我們是在寫(xiě)正則表達(dá)式, 不知道會(huì)匹配到什么, 可以用分組來(lái)解決.
(exp): 匹配exp, 并捕獲文本到自動(dòng)命名的組里. 然后用這些組的編號(hào)來(lái)調(diào)用, 最左邊定的分組編號(hào)是1, 以此類推. 例如’(\w).*?\1’ 可以匹配, ‘a(chǎn)fuckafuckf’ 中的’afucka’ 和’fuckf’ 這樣的字符串, 注意, 因?yàn)檫€沒(méi)有匹配, 所以分組捕獲的實(shí)際字符串是什么沒(méi)有確定, 只有開(kāi)始具體的字符串后, 才能知道分組匹配的是什么.
(?<>exp): 匹配exp, 在<>里面可以寫(xiě)分組的名字,但是調(diào)用分組的時(shí)候還是要寫(xiě)編號(hào), 估計(jì)這個(gè)分組只是一個(gè)注釋作用吧, 也可以寫(xiě)成(?’name’exp). 此處要吐槽CSDN這格式是個(gè)什么玩意.
(?:exp): 有時(shí)候要用()來(lái)改變匹配的優(yōu)先級(jí), 就要寫(xiě)成(?:)不然優(yōu)先級(jí)是改變了, 但是把不想分組的內(nèi)容分了組, 給了編號(hào), 可能會(huì)有不便.
分組0對(duì)應(yīng)整個(gè)正則表達(dá)式.
實(shí)際上組號(hào)分配過(guò)程是要從左向右掃描兩遍的:第一遍只給未命名組分配,第二遍只給命名組分配, 因此所有命名組的組號(hào)都大于未命名的組.
零寬斷言
斷言用來(lái)聲明一個(gè)應(yīng)該為真的事實(shí)。正則表達(dá)式中只有當(dāng)斷言為真時(shí)才會(huì)繼續(xù)進(jìn)行匹配。
正向:
(?=exp): 匹配以exp結(jié)尾的字符串, 不包快這個(gè)exp, 例如’\w(?=\d)’ 代表一個(gè)\w字符, 這個(gè)字符必須以數(shù)字結(jié)尾, 如果用來(lái)匹配’1a2bcde’, 匹配到的是a.
(?<=exp): 匹配以exp開(kāi)頭的字符串. 上面的例子:’(?<=\d)\w’ 匹配到的是a和b
負(fù)向:
(?!exp): 匹配不能以exp結(jié)尾的字符串.
(?<!exp): 匹配不能以exp開(kāi)頭的字符串.
注釋
(?#comment) 這種類型的分組不對(duì)正則表達(dá)式的處理產(chǎn)生任何影響,用于提供注釋讓人閱讀
1.3 一般的軟件模式
這些模式用于不同的需求. 以RegExTexter.exe為例, 默認(rèn)模式, 就是. 不能代表?yè)Q行符的單行模式.
IgnoreCase(忽略大小寫(xiě))模式:
匹配時(shí)不區(qū)分大小寫(xiě)。
Multiline(多行模式):
根據(jù)換行符, 把文本換行, 但是不去掉換行符.
主要作用就是, 變出了很多個(gè)行首和行尾.
Singleline(單行模式)
更改.的含義,使它與每一個(gè)字符匹配(包括換行符\n)。
2. re模塊
python中有適用于正則表達(dá)式的模塊, 就是re模塊.
在python中有兩種使用正則表達(dá)式的方法, 第一種是, 用re下的方法直接匹配, 但是需要以字符串的形式輸入正則表達(dá)式; 第二種是, 把正則表達(dá)式生成一個(gè)regex對(duì)象, 然后調(diào)用這個(gè)對(duì)象的方法來(lái)匹配.
匹配的返回值可以是str或者是match對(duì)象, match對(duì)象里面包含了匹配到的字符串的內(nèi)容和索引.
python也提供了幾種不同的模式來(lái)匹配:
re.I
re.IGNORECASE #這個(gè)模式是忽略字母的大小寫(xiě)
re.M
re.MULTILINE #多行模式
re.S
re.DOTALL #這個(gè)模式下, .也可以代表?yè)Q行符
re.X
re.VERBOSE #忽略大小寫(xiě)模式, 可以讓正則表達(dá)式看起來(lái)更好看, 我覺(jué)得還是別用吧
2.1 直接匹配:
re.match(pattern, string, flags=0)
pattern是正則表達(dá)式, string是要匹配的文本, flags是選擇用什么模式來(lái)匹配.
就是錨定開(kāi)頭, 這個(gè)正則表達(dá)式, 如果不再開(kāi)頭的話, 就算沒(méi)找到
匹配到了, 返回match對(duì)象. 沒(méi)匹配到, 什么都不返回.
import re a = re.match('\d', '123r123')print(a) (<_sre.SRE_Match object; span=(0, 1), match='1'>)re.search(pattern, string, flags=0)
同樣值匹配一次, 但是沒(méi)有錨定開(kāi)頭
re.fullmatch(pattern, string, flags=0)
看整個(gè)字符串是否符合正則表達(dá)式
re.findall(pattern, string, flags=0)
從整個(gè)字符串開(kāi)始匹配, 找到結(jié)果, 把結(jié)果以列表的形式返回.
re.finditer(pattern, string, flags=0)
也是從整個(gè)字符串里找
返回一個(gè)迭代器, 每次迭代出符合條件的match對(duì)象
re.sub(pattern, repl, string, count=0, flags=0)
在string里找到符合pattern的字符串, 把它替換成repl,
count指定替換次數(shù), 默認(rèn)是0, 就是全局替換,
返回的是替換好的字符串.
re.subn(pattern, repl, string, count=0, flags=0)
跟上面那個(gè)用法一毛一樣, 區(qū)別就是, 這個(gè)會(huì)返回一個(gè)二元組, 第一個(gè)元素是替換好的string, 第二個(gè)元素是替換次數(shù).
(?<=<(\w+)>).*(?=<\/\1>)匹配不包含屬性的簡(jiǎn)單HTML標(biāo)簽內(nèi)里的內(nèi)容。
re.split(pattern, string, maxsplit=0, flags=0)
把string中符合pattern的字符串都切掉, 和str.split()效果差不多, maxsplit是指定切割次數(shù)的.
2.2 生成regex對(duì)象再匹配
re.compile(pattern, flags=0)
用標(biāo)識(shí)符來(lái)接收, 注意, 這個(gè)對(duì)象是要在匹配之前設(shè)置好匹配模式的.
然后regex的方法和re的方法差不多, 后面只放目標(biāo)string就行了, 但是可以指定開(kāi)始和結(jié)束的位置:
regex.match(string[, pos[, endpos]])
regex.search(string[, pos[, endpos]])
regex.fullmatch(string[, pos[, endpos]])
regex.findall(string[, pos[, endpos]])
regex.finditer(string[, pos[, endpos]])
regex.sub(repl, string, count=0)
regex.subn(repl, string, count=0)
regex.split(string, maxsplit=0)
3. match對(duì)象
match.group([group1, …])
后面括號(hào)寫(xiě)分組的編號(hào), 可以得到字符串形式的分組
match.groups(default=None)
可以把所有的分組放在一個(gè)元組里面返回來(lái)
match.groupdict(default=None)
如果給分組命名了的話, 注意python中分組要用(?P<’name’>)來(lái)命名, 這個(gè)方法可以返回一個(gè)字典.
總結(jié)
以上是生活随笔為你收集整理的Python的正则表达式和re模块的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 蓝牙耳机按键事件linux,【记录】An
- 下一篇: python小课堂28_python小课