本博文源於python基礎,主要探討re模塊的分組匹配與匹配對象使用。
正則概述
正則的原理是《自動機》這門課講的內容。
1986年圖靈獎–約翰·霍普克洛夫特和羅伯特·陶爾揚簡介這門課的創始人就是他們,有興趣點開看看。之前也做過所有圖靈獎大佬合集,也可以看看。正則的原理,我也做了博文。因此,再學正則就會發現很親近。無非就這些元字符的排列組合。python外加封裝罷了。
大家在學習下面的時候,不要慌亂。謹記一條口訣:先看標題講了啥,再看內容有沒有跟之前學過相似。類比學習。
re模塊
re是python正則模塊標準庫
正則匹配搜索函數
這裏有兩個函數作正則匹配,一個是match,另一個是search。當博主去百度搜索的時候,發現match是匹配搜個,search是從全體字符串尋找匹配。而findall是一個查找所有並返回列表,而前面兩個是返回對象。我們先看原型
re.match(pattern,string[,flags])
re.search(pattern,string[,flags])
re.findall(pattern,string[,flags])
- pattern 正則匹配模式
- string 要進行匹配的字符串
- flags 可選參數,進行匹配的標誌.(flags細講)
flag選項 | 意義 |
---|---|
re.I | 忽略大小寫 |
re.L | 根據本地設置而更改\w.\W.\b.\B.\s,以及\S的匹配內容 |
re.M | 多行匹配模式 |
re.S | 使"."元字符也匹配換行符 |
re.U | 匹配Unicode字符 |
re.X | 忽略pattern中的空格,並且可以使用“#” |
這裏演示一下match和search、findall匹配。打開ipython演示喲!
In [11]: s = 'Life can be good'
In [12]: import re
In [13]: print(re.match('life',s,re.I))
<re.Match object; span=(0, 4), match='Life'>
In [14]: print(re.match('life',s))
None
In [15]: print(re.search('be',s))
<re.Match object; span=(9, 11), match='be'>
In [16]: print(re.findall('[a-z]{1,3}',s))
['ife', 'can', 'be', 'goo', 'd']
In [17]:
sub()與subn()函數
這兩個函數多了一個n,就當作是附加次數的意思
- sub返回替換後的字符串
- subn返回一個元組,元組包括替換後的字符串和一共替換的次數
re.sub(pattern,repl,string[,count])
re.subn(pattern,repl,string[,count])
- pattern 正規表達式模式
- repl 要替換成的內容
- string 進行內容替換的字符串
- count 可選參數,最大替換次數
In [18]: import re
In [19]: s = 'Life can be bad'
In [20]: print(re.sub('bad|be','good',s,1))
Life can good bad
In [21]: s
Out[21]: 'Life can be bad'
In [22]: print(re.subn('bad|be','good',s,1))
('Life can good bad', 1)
In [23]:
split()函數
想想python本身就有分割。然後正則再來一個分割。其實re.split()函數用於分割字符串,它返回分割後的字符串列表。
re.split(pattern,string[,maxsplit = 0])
- pattern 正則表達式模式
- string 要分割的字符串
- maxsplit 可選參數,最大分割次數
In [23]: s = 'I2like3py4rex5'
In [24]: re.split('\d',s)
Out[24]: ['I', 'like', 'py', 'rex', '']
In [25]:
正則表達式對象
講到這裏大家可以鬆口氣了,這裏不過是給我們廣大程序員一個方便的。它將正則實例化方便我們多次使用。所以官方叫做預編譯,總所周知編譯完成爲可執行程序它的內容就被固定下來,這裏也是同理。讓我們一起體驗一下吧!
compile(pattern[,flags])
- pattern 正則表達式匹配模式
- flags 可選參數,編譯標誌
預編譯完畢,是要執行的,執行的有幾個屬性跟上面講過的一致,下面就一起帶過吧
match()
跟上面的match相同,要匹配的字符串位於開始
match(string[,pos[,endpos]])
- string 要進行匹配的字符串
- pos 可選參數,進行匹配的起始位置
- endpos 可選參數,進行匹配的結束位置
search()
跟上面的search類似,全體字符串中查詢
search(string[,pos[,endpos]])
- string 要進行匹配的字符串
- pos 可選參數,進行匹配的起始位置
- endpos 可選參數,進行匹配的結束位置
findall()
findall(string[,pos[,endpos]])
跟上面的findall類似
sub()和subn()
跟上面的sub與subn同理
sub(repl,string[,count=0])
subn(repl,string[,count=0])
- repl 要替換成的內容
- string 進行內容替換的字符串
- count 可選參數,最大替換次數
split()
與上面的split類似
split(string[,maxsplit=0])
- string 要分割的字符串
- maxsplit 可選參數,最大分割次數
這裏我們將簡單測試一二
例子:給定一個字符串,以數字切割
- I1like2python3
In [26]: import re
In [27]: rex = re.compile('\d')
In [28]: s = 'I1like2python3'
In [29]: rex.split(s)
Out[29]: ['I', 'like', 'python', '']
分組匹配與匹配對象使用
知道了前面那麼多,爲什麼還要學習這個?因爲有一些字符串往往有規律,分成組後更容易操作
例如:
- 郵箱的規則
- 郵編的規則
- 號碼的規則等等
分組基礎
python以一對圓括號"()"來表示位於其中的內容屬於一個分組
例子:演示用正則分割號碼的區號和本地號碼
In [41]: import re
In [42]: s = 'Phone No. 010-87654321'
In [43]: r = re.compile(r'(\d+)-(\d+)')
In [44]: m = r.search(s)
In [45]: m
Out[45]: <re.Match object; span=(10, 22), match='010-87654321'>
In [46]: m.groups()
Out[46]: ('010', '87654321')
In [47]:
分組擴展
小朋友頭上是否有很多問號?確實!分組擴展(?<組名>)遍地都是問號
擴展語法 | 意義 |
---|---|
(?Lmsux) | 設置匹配標誌,可以是左邊字符以及它們的組合,其含義與編譯標誌相同 |
(?:…) | 匹配但不捕獲該匹配的子表達式 |
(?P=name) | 表示在此之前的名爲name的組 |
(?#…) | 表示註釋 |
(?=…) | 用於正則表達式之後,表示如果"=“後的內容在字符串中出現則匹配,但不返回”="後的內容 |
(?!..) | 用於正則表達式之後,表示如果"!“後的內容在字符串中出現則匹配,但不返回”!"後的內容 |
(?<=…) | 用於正則表達式之前,與(?=…)含義相同 |
(?<!..) | 用於正則表達式之前,與(?!..)含義相同 |
匹配對象與組的使用
三個函數可以查看最後的結果
group([group1,...])# 返回字符串
groups([default]) # 返回元組
groupdict([default]) # 返回字典
例子:匹配所有包含字母“a”的單詞
使用group,groups,groupdict輸出他們
In [84]: import re
In [85]: s = '''Life can be dreams,
...: Life can be great thoughts;
...: Life can mean a person,
...: Sitting in a court.'''
In [86]: r = re.compile('\\b(?P<first>\w+)a(\w+)\\b')
In [87]: m = r.search(s)
In [88]: m.groupdict()
Out[88]: {'first': 'c'}
In [89]: m.groups()
Out[89]: ('c', 'n')
In [90]: m.group(1)
Out[90]: 'c'
In [91]:
匹配對象與索引使用
一共有三個原型
start([groupid=0])
end([groupid=0])
span(groupid=0)
- groupid爲可選參數,即分組編號,如果不傳,返回整個字符串索引
- start()返回字符串起始索引
- end()返回字符結束位置索引
- span()則以元組返回以上的兩者
例子:匹配所有包含a的單詞,用索引進行輸出
In [95]: r = re.compile('\\b(?P<first>\w+)a(\w+)\\b')
In [96]: m = r.search(s,9)
In [97]: m.start()
Out[97]: 12
In [98]: m.start(1)
Out[98]: 12
In [99]: m.start(2)
Out[99]: 16
In [100]: m.end(1)
Out[100]: 15
In [101]: m.end()
Out[101]: 18
In [102]: m.span()
Out[102]: (12, 18)
In [103]: m.span(2)
Out[103]: (16, 18)
In [104]: