你說要你想玩爬蟲,但你說你不懂Python正則表示式,我信你個鬼,那你還不來看看?
前言
正則表示式是一個特殊的字元序列,它能幫助你方便的檢查一個字串是否與某種模式匹配。
re 模組也提供了與這些方法功能完全一致的函式,這些函式使用一個模式字串做為它們的第一個引數。
re.match函式
re.match 嘗試從字串的起始位置匹配一個模式,如果不是起始位置匹配成功的話,match()就返回none。
函式語法:
re.match(pattern, string, flags=0)
函式引數說明:
引數 | 描述 |
---|---|
pattern | 匹配的正則表示式 |
string | 要匹配的字串。 |
flags | 標誌位,用於控制正則表示式的匹配方式,如:是否區分大小寫,多行匹配等等。 |
匹配成功re.match方法返回一個匹配的物件,否則返回None。
我們可以使用group(num) 或 groups() 匹配物件函式來獲取匹配表示式。
匹配物件方法 | 描述 |
---|---|
group(num=0) | 匹配的整個表示式的字串,group() 可以一次輸入多個組號,在這種情況下它將返回一個包含那些組所對應值的元組。 |
groups() | 返回一個包含所有小組字串的元組,從 1 到 所含的小組號。 |
例項:
import re line = "I really like you yesterday" matchObj = re.match( r'(.*) really (.*?) .*', line) print ("matchObj.group() : ", matchObj.group())print ("matchObj.group(1) : ", matchObj.group(1))print ("matchObj.group(2) : ", matchObj.group(2))
以上例項執行結果如下:
matchObj.group() : I really like you yesterdaymatchObj.group(1) : ImatchObj.group(2) : like
re.search方法
re.search 會在字串內查詢模式匹配,直到找到第一個匹配。
函式語法:
re.search(pattern, string, flags=0)
函式引數說明:
引數 | 描述 |
---|---|
pattern | 匹配的正則表示式 |
string | 要匹配的字串。 |
flags | 標誌位,用於控制正則表示式的匹配方式,如:是否區分大小寫,多行匹配等等。 |
匹配成功re.search方法返回一個匹配的物件,否則返回None。
我們可以使用group(num) 或 groups() 匹配物件函式來獲取匹配表示式。
匹配物件方法 | 描述 |
---|---|
group(num=0) | 匹配的整個表示式的字串,group() 可以一次輸入多個組號,在這種情況下它將返回一個包含那些組所對應值的元組。 |
groups() | 返回一個包含所有小組字串的元組,從 1 到 所含的小組號。 |
例項:
#!/usr/bin/python
import re
line = "I really like you yesterday";
searchObj = re.search(r'(.*) really (.*?) .*', line)
print ("searchObj.group() : ", searchObj.group())
print ("searchObj.group(1) : ", searchObj.group(1))
print ("searchObj.group(2) : ", searchObj.group(2))
以上例項執行結果如下:
searchObj.group() : I really like you yesterday
searchObj.group(1) : I
searchObj.group(2) : love
re.match與re.search的區別
re.match只匹配字串的開始,如果字串開始不符合正則表示式,則匹配失敗,函式返回None;而re.search匹配整個字串,直到找到一個匹配。
例項:
#!/usr/bin/python
import re
line = "I really like you yesterday";
matchObj = re.match( r'love', line)
if matchObj:
print("match --> matchObj.group() : ", matchObj.group())
else:
print "No match!!"
matchObj = re.search( r'love', line)
if matchObj:
print "search --> matchObj.group() : ", matchObj.group()
else:
print "No match!!"
以上例項執行結果如下:
No match!!
search --> matchObj.group() : love
檢索和替換
Python 的re模組提供了re.sub用於替換字串中的匹配項。
語法:
re.sub(pattern, repl, string, max=0)
返回的字串是在字串中用 RE 最左邊不重複的匹配來替換。如果模式沒有發現,字元將被沒有改變地返回。
可選引數 count 是模式匹配後替換的最大次數;count 必須是非負整數。預設值是 0 表示替換所有的匹配。
例項:
import re
phone = "2004-959-559 # 這是一個國外電話號碼"
# 刪除字串中的 Python註釋
num = re.sub(r'#.*$', "", phone)
print("電話號碼是: ", num)
# 刪除非數字(-)的字串
num = re.sub(r'\D', "", phone)
print("電話號碼是 : ", num)
以上例項執行結果如下:
電話號碼 : 2004-959-559
電話號碼 : 2004959559
repl 引數是一個函式
以下例項中將字串中的匹配的數字乘以 2:
例項:
import re
# 將匹配的數字乘以 2
def double(matched):
value = int(matched.group('value'))
return str(value * 2)
s = 'A23G4HFD567'
print(re.sub('(?P<value>\d+)', double, s))
執行輸出結果為:
A46G8HFD1134
re.compile 函式
compile 函式用於編譯正則表示式,生成一個正則表示式( Pattern )物件,供 match() 和 search() 這兩個函式使用。
語法格式為:
re.compile(pattern[, flags])
引數:
-
pattern : 一個字串形式的正則表示式
-
flags : 可選,表示匹配模式,比如忽略大小寫,多行模式等,具體引數為:
-
- re.I 忽略大小寫
- re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依賴於當前環境
- re.M 多行模式
- re.S 即為 . 並且包括換行符在內的任意字元(. 不包括換行符)
- re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依賴於 Unicode 字元屬性資料庫
- re.X 為了增加可讀性,忽略空格和 # 後面的註釋
例項
>>>import re
>>> pattern = re.compile(r'\d+') # 用於匹配至少一個數字
>>> m = pattern.match('one12twothree34four') # 查詢頭部,沒有匹配
>>> print (m)
None
>>> m = pattern.match('one12twothree34four', 2, 10) # 從'e'的位置開始匹配,沒有匹配
>>> print (m)
None
>>> m = pattern.match('one12twothree34four', 3, 10) # 從'1'的位置開始匹配,正好匹配
>>> print (m) # 返回一個 Match 物件
<_sre.SRE_Match object at 0x10a42aac0>
>>> m.group(0) # 可省略 0
'12'
>>> m.start(0) # 可省略 0
3
>>> m.end(0) # 可省略 0
5
>>> m.span(0) # 可省略 0
(3, 5)
在上面,當匹配成功時返回一個 Match 物件,其中:
- group([group1, …]) 方法用於獲得一個或多個分組匹配的字串,當要獲得整個匹配的子串時,可直接使用 group() 或 group(0);
- start([group]) 方法用於獲取分組匹配的子串在整個字串中的起始位置(子串第一個字元的索引),引數預設值為 0;
- end([group]) 方法用於獲取分組匹配的子串在整個字串中的結束位置(子串最後一個字元的索引+1),引數預設值為 0;
- span([group]) 方法返回 (start(group), end(group))。
再看看一個例子:
>>>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 at 0x10bea83e8>
>>> m.group(0) # 返回匹配成功的整個子串
'Hello World'
>>> m.span(0) # 返回匹配成功的整個子串的索引
(0, 11)
>>> m.group(1) # 返回第一個分組匹配成功的子串
'Hello'
>>> m.span(1) # 返回第一個分組匹配成功的子串的索引
(0, 5)
>>> m.group(2) # 返回第二個分組匹配成功的子串
'World'
>>> m.span(2) # 返回第二個分組匹配成功的子串
(6, 11)
>>> m.groups() # 等價於 (m.group(1), m.group(2), ...)
('Hello', 'World')
>>> m.group(3) # 不存在第三個分組
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: no such group
findall
在字串中找到正則表示式所匹配的所有子串,並返回一個列表,如果沒有找到匹配的,則返回空列表。
注意:match 和 search 是匹配一次 findall 匹配所有。
語法格式為:
findall(string[, pos[, endpos]])
引數:
- string : 待匹配的字串。
- pos : 可選引數,指定字串的起始位置,預設為 0。
- endpos : 可選引數,指定字串的結束位置,預設為字串的長度。
查詢字串中的所有數字:
import re
pattern = re.compile(r'\d+') # 查詢數字
result1 = pattern.findall('school 123 google 456')
result2 = pattern.findall('sch88ool123google456', 0, 10)
print(result1)
print(result2)
輸出結果:
['123', '456']
['88', '12']
re.finditer
和 findall 類似,在字串中找到正則表示式所匹配的所有子串,並把它們作為一個迭代器返回。
re.finditer(pattern, string, flags=0)
引數:
引數 | 描述 |
---|---|
pattern | 匹配的正則表示式 |
string | 要匹配的字串。 |
flags | 標誌位,用於控制正則表示式的匹配方式,如:是否區分大小寫,多行匹配等等。 |
例項:
import re
it = re.finditer(r"\d+","12a32bc43jf3")
for match in it:
print (match.group() )
輸出結果:
12
32
43
3
re.split
split 方法按照能夠匹配的子串將字串分割後返回列表,它的使用形式如下:
re.split(pattern, string[, maxsplit=0, flags=0])
引數:
引數 | 描述 |
---|---|
pattern | 匹配的正則表示式 |
string | 要匹配的字串。 |
maxsplit | 分隔次數,maxsplit=1 分隔一次,預設為 0,不限制次數。 |
flags | 標誌位,用於控制正則表示式的匹配方式,如:是否區分大小寫,多行匹配等等。 |
例項:
>>>import re
>>> re.split('\W+', 'school, school, chool.')
['runoob', 'runoob', 'w3cschool', '']
>>> re.split('(\W+)', ' school, school, school.')
['', ' ', 'runoob', ', ', 'school', ', ', 'school', '.', '']
>>> re.split('\W+', ' w3cschool, w3cschool, w3cschool.', 1)
['', 'school, school, school.']
>>> re.split('a*', 'hello world') # 對於一個找不到匹配的字串而言,split 不會對其作出分割
['hello world']