python中提供了re這個模塊提供對正則表達式的支持。python
1、正則表達式經常使用到的一些語法(並不是所有):正則表達式
. | 匹配任意單個字符 |
[...] | 匹配單個字符集 |
\w | 匹配單詞字符,即[a-zA-Z0-9] |
\W | 匹配非單詞字符集,例如 ‘*’ |
\d | 匹配數字,即[0-9] |
\D | 匹配非數字 |
\s | 匹配空白字符 |
\S | 匹配非空白字符 |
* | 匹配前一個字符0次或者任意屢次 |
+ | 匹配前一個字符1次或者任意屢次 |
? | 匹配前一個字符0次或者1次 |
{m} | 匹配前一個字符m次 |
{m,n} | 匹配前一個字符最少m次,最多n次 |
*? | 非貪婪模式匹配前一個字符0次或者任意屢次 |
+? | 非貪婪模式匹配前一個字符1次或者任意屢次 |
?? | 非貪婪模式匹配前一個字符0次或者1次 |
{m,n}? | 非貪婪模式匹配前一個字符最少m次,最多n次 |
^ | 匹配字符串開頭 |
$ | 匹配字符串結尾 |
\A | 制定的字符串匹配必須出如今開頭 |
\Z | 制定的字符串匹配必須出如今結尾 |
| | 匹配左右任意一個表達式,至關於「或」的含義 |
() | 匹配一個分組,括號中爲該分組所需匹配的內容 |
\<number> | 引用匹配編號爲<number>的分組中的字符串 |
(?P<group_name>) | 爲匹配分組制定特定的組名 |
(?P=<group_name>) | 引用特定組名的匹配字符串 |
幾點解釋:函數
1. 兩種方式均可以進行匹配:spa
(1)首先建立pattern,而後進行matchcode
1 pa = re.compile(r'[\w]{6}') # 首先利用re模塊建立一個pattern實例pa 2 ma = pa.match('string') # 利用這一pattern對正則表達式進行匹配 3 ma.group() #打印匹配的內容,輸出爲'string'
(2)直接利用re模塊中的函數match進行匹配對象
1 ma = re.match(r'[\w]{6}', ‘string’) 2 print(ma.group()) # 打印匹配的內容,輸出爲'string'
2. 貪婪模式和非貪婪模式:blog
貪婪模式:老是嘗試匹配儘量多的字符;ci
非貪婪模式:老是嘗試匹配儘量少的字符。字符串
例如:利用正則表達式‘python*’匹配‘pythonnnnnpython’,此時ma = re.match(r'python*',‘pythonnnpython’),獲得的ma.group()爲‘pythonnn’;利用‘python*?’進行匹配,此時ma = re.match(r'python*?',‘pythonnnpython’),獲得的ma.group()爲‘python’。博客
3. 關於邏輯與分組語法的用法:
| | 匹配左右任意一個表達式,至關於「或」的含義 |
() | 匹配一個分組,括號中爲該分組所需匹配的內容 |
\<number> | 引用匹配編號爲<number>的分組中的字符串 |
(?P<group_name>) | 爲匹配分組制定特定的組名 |
(?P=<group_name>) | 引用特定組名的匹配字符串 |
首先,|和()的用法比較容易理解,例如咱們須要匹配多個郵箱的地址是否合法,例若有gmail郵箱、outlook郵箱,假定@前的字符數爲6到20個,此時能夠寫成:
1
2
3
4
5
6
7
|
>>> pa
=
re.
compile
(
'[\w]{6,20}@(gmail|outlook).com$'
)
>>> ma
=
pa.match(
'bokeyuan@gmail.com'
)
>>> ma.group()
'bokeyuan@gmail.com'
>>> ma
=
pa.match(
'bokeyuan@outlook.com'
)
>>> ma.group()
'bokeyuan@outlookl.com'
|
後邊三個的用法根據下邊的例子進行說明:
1
2
3
4
5
6
7
8
9
10
|
>>>
str
=
'<code>python</code>'
>>> ma
=
re.match(r
'<[\w]+>'
,
str
)
>>> ma.group()
'<code>'
>>> ma
=
re.match(r
'<([\w]+>)[\w]+</\1'
,
str
)
>>> ma.group()
'<code>python</code>'
>>> ma
=
re.match(r
'<(?P<group1>[\w]+>)[\w]+</(?P=group1)'
,
str
)
>>> ma.group()
'<code>python</code>'
|
其中,第一個例子就是對字符串‘<code>'進行匹配。咱們發現str中其實有兩部分是徹底相同的,就是都含有'code>'這個substring,因而能夠看第二個例子,咱們用()將([\w]+>)這部份內容括住時,這部分匹配的字符串就是'code>',([\w]+>)就是一個分組,沒有起名字的狀況下默認<number>爲1,所以在咱們須要在末尾再次引用到它的時候,就寫上 /1 便可。第三個例子與第二個例子的效果徹底相同,只不過爲了更加清楚的記住匹配分組的名字,咱們利用(?P<group_name>)這一語法功能,人爲的爲這個分組取了一個group1的名字,在最後又引用了這一分組。
4. 注意字符串中轉義字符的問題
上述例子中,出如今正則表達式前邊的r是原始字符串操做符,能夠寫爲r或者R:表示字符串內的全部字符都按原始意思解釋。
例如:‘c:\python\test.py’ 若是不加r,則計算機會將 \t 會變成轉義字符解釋;加上r之後,寫爲:r‘c:\python\test.py’,計算機就會直接輸出c:\python\test.py,不然要想輸出c:\python\test.py,必須將字符串寫爲‘c:\\python\\test.py’
2、介紹幾個re模塊中的經常使用函數
1. search(pattern, string, flags=0)函數
search函數功能:在字符串中查找匹配
例如:博客會記錄來訪者的數量,咱們經過正則匹配查找字符串中的數字:
1 str1 = 'number of visitors = 1000' 2 info = re.search(r'\d+', str1) # 匹配字符串str1中的數字 3 print('訪客數量:', info) 4 print(info.group()) # 顯示匹配的內容
固然,上述操做也能夠經過對字符串直接操做得到,例如:print('訪客數量:', str1.find('1000')) 。可是這樣存在一個問題,由於訪客數量實在不斷變化的,一旦1000這個數字增長,用字符串操做就難以實現。可是利用search函數就不存在這樣的問題。
2. findall(pattern, string, flags=0)函數
findall函數功能:找到匹配,並返回全部匹配內容的列表
例如,博客記錄了最近三天天天的訪客記錄,咱們須要將三天的訪客數量都查找出來,並計算總的訪客數量,此時用search函數沒法直接將三天的訪客數量同時提取,能夠採用findall函數:
1 str2 = 'day1=22, day2=34, day3=13' 2 info = re.findall(r'=[\d]+', str2) 3 print(info) 4 print('三天的訪客數量爲:', sum([int(x[1:]) for x in info]))
3. sub(pattern, repl, string, count=0, flags=0)函數
sub函數功能:將字符串中匹配正則表達式的部分替換爲其餘值。其中repl能夠是一個字符串,也能夠是一個函數。
當repl是一個字符串時,仍然以訪客記錄爲例,當增長一個訪客時,須要修改記錄中的數字:
1 str3 = 'number of visitors = 1000' 2 info = re.sub(r'[\d]+', '1001', str3) 3 print(info) # 此時輸出結果爲 number of visitors = 1001
可是此時每次修改都必須手動輸入數字,顯然,對於這種隨時變化的數字來講,這種操做是不合理的。而sub函數的高明之處就是容許repl是一個函數。
當repl爲一個函數時,首先會在string中查找pattern的匹配,查找到的匹配是一個match對象,這個match對象就會被傳遞到repl這個函數中。上述例子能夠這樣實現:
1 # 首先,定義一個增長訪客數量的函數,函數的參數是一個match對象 2 def add_num(match): 3 val = match.group() 4 num = int(val) + 1 5 return str(num) 6 7 str3 = 'number of visitors = 1000' 8 print('最新訪客數量:', re.sub(r'[\d]+', add_num, str3)) # 打印結果,最新訪客數量:number of visitors = 1001
4. split(pattern, string, maxsplit=0, flags=0)函數
split函數功能:根據匹配分割字符串,返回分割字符串組成的列表
1 str4 = 'day1=22, day2=34, day3=13' 2 print(re.split(r', ', str4)) # 打印出的內容爲 ['day1=22', 'day2=34', 'day3=13']