@
- 1 正規表示式
- 1.1 簡介
- 1.2 match和search
- 1.2.1 re.match函式
- 1.2.2 re.search方法
- 1.2.3 re.match 與 re.search的區別
- 1.3 檢索和替換
- 1.3.1 re.sub
- 1.3.2 compile
- 1.3.3 findall
- 1.3.4 re.finditer
- 1.3.5 re.split
- 1.4 正規表示式物件
- 1.5 正規表示式修飾符
- 1.5.1 可選標誌
- 1.5.2 正規表示式模式
1 正規表示式
1.1 簡介
正規表示式是一個特殊的字元序列,它能方便的檢查一個字串是否與某種模式匹配。
在 Python 中,使用 re
模組來處理正規表示式。
re
模組提供了一組函式,允許你在字串中進行模式匹配、搜尋和替換操作。
re
模組使 Python
語言擁有完整的正規表示式功能。
1.2 match和search
1.2.1 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
print(re.match('www', 'www.baidu.com').span()) # 在起始位置匹配
print(re.match('com', 'www.baidu.com')) # 不在起始位置匹配
輸出結果為:
(0, 3)
None
import re
line = "Cats are smarter than dogs"
# .* 表示任意匹配除換行符(\n、\r)之外的任何單個或多個字元
# (.*?) 表示"非貪婪"模式,只儲存第一個匹配到的子串
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)
if matchObj:
print ("matchObj.group() : ", matchObj.group())
print ("matchObj.group(1) : ", matchObj.group(1))
print ("matchObj.group(2) : ", matchObj.group(2))
else:
print ("No match!!")
執行結果如下:
matchObj.group() : Cats are smarter than dogs
matchObj.group(1) : Cats
matchObj.group(2) : smarter
1.2.2 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 到 所含的小組號。
import re
print(re.search('www', 'www.baicu.com').span()) # 在起始位置匹配
print(re.search('com', 'www.baidu.com').span()) # 不在起始位置匹配
以上例項執行輸出結果為:
(0, 3)
(11, 14)
import re
line = "Cats are smarter than dogs"
searchObj = re.search( r'(.*) are (.*?) .*', line, re.M|re.I)
if searchObj:
print ("searchObj.group() : ", searchObj.group())
print ("searchObj.group(1) : ", searchObj.group(1))
print ("searchObj.group(2) : ", searchObj.group(2))
else:
print ("Nothing found!!")
執行結果如下:
searchObj.group() : Cats are smarter than dogs
searchObj.group(1) : Cats
searchObj.group(2) : smarter
1.2.3 re.match 與 re.search的區別
re.match
只匹配字串的開始,如果字串開始不符合正規表示式,則匹配失敗,函式返回 None,而 re.search
匹配整個字串,直到找到一個匹配。
import re
line = "Cats are smarter than dogs"
matchObj = re.match( r'dogs', line, re.M|re.I)
if matchObj:
print ("match --> matchObj.group() : ", matchObj.group())
else:
print ("No match!!")
matchObj = re.search( r'dogs', line, re.M|re.I)
if matchObj:
print ("search --> matchObj.group() : ", matchObj.group())
else:
print ("No match!!")
執行結果如下:
No match!!
search --> matchObj.group() : dogs
1.3 檢索和替換
1.3.1 re.sub
Python 的re模組提供了re.sub
用於替換字串中的匹配項。
語法:re.sub(pattern, repl, string, count=0, flags=0)
pattern
:正則中的模式字串。repl
:替換的字串,也可為一個函式。string
:要被查詢替換的原始字串。count
:模式匹配後替換的最大次數,預設 0 表示替換所有的匹配。flags
:編譯時用的匹配模式,數字形式。
前三個為必選引數,後兩個為可選引數。
import re
phone = "2004-959-559 # 這是一個電話號碼"
# 刪除註釋
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
1.3.2 compile
compile
函式用於編譯正規表示式,生成一個正規表示式( Pattern
)物件,供 match() 和 search()
這兩個函式使用。
語法格式為:re.compile(pattern[, flags])
pattern
:一個字串形式的正規表示式flags
:可選,表示匹配模式,比如忽略大小寫,多行模式等,具體引數為:re.IGNORECASE 或 re.I
:- 使匹配對大小寫不敏感re.L
:表示特殊字符集 \w, \W, \b, \B, \s, \S 依賴於當前環境re.MULTILINE 或 re.M
:多行模式,改變^
和$
的行為,使它們匹配字串的每一行的開頭和結尾。re.DOTALL 或 re.S
:使 . 匹配包括換行符在內的任意字元。re.ASCII
:使 \w, \W, \b, \B, \d, \D, \s, \S 僅匹配 ASCII 字元。re.VERBOSE 或 re.X
:忽略空格和註釋,可以更清晰地組織複雜的正規表示式。
這些標誌可以單獨使用,也可以透過按位或(|
)組合使用。例如, re.IGNORECASE | re.MULTILINE
表示同時啟用忽略大小寫和多行模式。
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
1.3.3 findall
在字串中找到正規表示式所匹配的所有子串,並返回一個列表,如果有多個匹配模式,則返回元組列表,如果沒有找到匹配的,則返回空列表。
注意
: match
和 search
是匹配一次 findall
匹配所有。
語法格式為:re.findall(pattern, string, flags=0)
或 pattern.findall(string[, pos[, endpos]])
引數:
pattern
:匹配模式。string
:待匹配的字串。pos
:可選引數,指定字串的起始位置,預設為 0。endpos
:可選引數,指定字串的結束位置,預設為字串的長度。
查詢字串中的所有數字:
import re
result1 = re.findall(r'\d+','test 123 google 456')
pattern = re.compile(r'\d+') # 查詢數字
result2 = pattern.findall('test 123 google 456')
result3 = pattern.findall('te88st123google456', 0, 10)
print(result1)
print(result2)
print(result3)
輸出結果:
['123', '456']
['123', '456']
['88', '12']
多個匹配模式,返回元組列表:
import re
result = re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10')
print(result)
[('width', '20'), ('height', '10')]
1.3.4 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
1.3.5 re.split
split
方法按照能夠匹配的子串將字串分割後返回列表,它的使用形式如下:re.split(pattern, string[, maxsplit=0, flags=0])
pattern
:匹配的正規表示式string
:要匹配的字串。maxsplit
:分割次數,maxsplit=1
分割一次,預設為 0,不限制次數。flags
:標誌位,用於控制正規表示式的匹配方式,如:是否區分大小寫,多行匹配等等
>>>import re
>>> re.split('\W+', 'baidu, baidu, baidu.')
['baidu', 'baidu', 'baidu', '']
>>> re.split('(\W+)', ' baidu, baidu, baidu.')
['', ' ', 'baidu', ', ', 'baidu', ', ', 'baidu', '.', '']
>>> re.split('\W+', ' baidu, baidu, baidu.', 1)
['', 'baidu, baidu, baidu.']
>>> re.split('a*', 'hello world') # 對於一個找不到匹配的字串而言,split 不會對其作出分割
['hello world']
1.4 正規表示式物件
re.RegexObject
re.compile()
返回 RegexObject 物件。
re.MatchObject
group()
返回被 RE 匹配的字串。
start()
:返回匹配開始的位置end()
:返回匹配結束的位置span()
:返回一個元組包含匹配 (開始,結束) 的位置
1.5 正規表示式修飾符
1.5.1 可選標誌
正規表示式可以包含一些可選標誌修飾符來控制匹配的模式。
以下標誌可以單獨使用,也可以透過按位或(|
)組合使用。例如,re.IGNORECASE | re.MULTILINE
表示同時啟用忽略大小寫和多行模式。
修飾符 | 描述 |
---|---|
re.IGNORECASE 或 re.I | 使匹配對大小寫不敏感 |
re.MULTILINE 或 re.M | 多行匹配,影響 ^ 和 $ ,使它們匹配字串的每一行的開頭和結尾。 |
re.DOTALL 或 re.S | 使 . 匹配包括換行符在內的任意字元。 |
re.ASCII | 使 \w, \W, \b, \B, \d, \D, \s, \S 僅匹配 ASCII 字元。 |
re.VERBOSE 或 re.X | 忽略空格和註釋,可以更清晰地組織複雜的正規表示式。 |
1.5.2 正規表示式模式
模式字串使用特殊的語法來表示一個正規表示式。
字母和數字表示他們自身。一個正規表示式模式中的字母和數字匹配同樣的字串。
多數字母和數字前加一個反斜槓時會擁有不同的含義。
標點符號只有被轉義時才匹配自身,否則它們表示特殊的含義。
反斜槓本身需要使用反斜槓轉義。
由於正規表示式通常都包含反斜槓,所以你最好使用原始字串來表示它們。模式元素(如 r'\t',等價於 \t )匹配相應的特殊字元。
模式 | 描述 |
---|---|
^ | 匹配字串的開頭 |
$ | 匹配字串的末尾 |
. |
匹配任意字元,除了換行符,當re.DOTALL標記被指定時,則可以匹配包括換行符的任意字元。 |
[...] | 用來匹配所包含的任意一個字元,例如 [amk] 匹配 'a','m'或'k' |
[^...] |
不在[]中的字元:[^abc] 匹配除了a,b,c之外的字元。 |
re* | 匹配0個或多個的表示式。 |
re+ | 匹配1個或多個的表示式。 |
re? | 匹配0個或1個由前面的正規表示式定義的片段,非貪婪方式 |
re | 匹配n個前面表示式。例如,"o{2}"不能匹配"Bob"中的"o",但是能匹配"food"中的兩個o。 |
re | 精確匹配n個前面表示式。例如,"o{2,}"不能匹配"Bob"中的"o",但能匹配"foooood"中的所有o。"o{1,}"等價於"o+"。"o{0,}"則等價於"o*"。 |
re | 匹配 n 到 m 次由前面的正規表示式定義的片段,貪婪方式 |
a| b | 匹配a或b |
(re) | 匹配括號內的表示式,也表示一個組 |
(?imx) | 正規表示式包含三種可選標誌:i, m, 或 x 。隻影響括號中的區域。 |
(?-imx) | 正規表示式關閉 i, m, 或 x 可選標誌。隻影響括號中的區域。 |
(?: re) | 類似 (...), 但是不表示一個組 |
(?imx: re) | 在括號中使用i, m, 或 x 可選標誌 |
(?-imx: re) | 在括號中不使用i, m, 或 x 可選標誌 |
(?#...) | 註釋. |
(?= re) | 前向肯定界定符。如果所含正規表示式,以 ... 表示,在當前位置成功匹配時成功,否則失敗。但一旦所含表示式已經嘗試,匹配引擎根本沒有提高;模式的剩餘部分還要嘗試界定符的右邊。 |
(?! re) | 前向否定界定符。與肯定界定符相反;當所含表示式不能在字串當前位置匹配時成功。 |
(?> re) | 匹配的獨立模式,省去回溯。 |
\w | 匹配數字字母下劃線 |
\W | 匹配非數字字母下劃線 |
\s | 匹配任意空白字元,等價於 [\t\n\r\f]。 |
\S | 匹配任意非空字元 |
\d | 匹配任意數字,等價於 [0-9] |
\D | 匹配任意非數字 |
\A | 匹配字串開始 |
\Z | 匹配字串結束,如果是存在換行,只匹配到換行前的結束字串 |
\z | 匹配字串結束 |
\G | 匹配最後匹配完成的位置。 |
\b | 匹配一個單詞邊界,也就是指單詞和空格間的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。 |
\B | 匹配非單詞邊界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。 |
\n, \t, | 匹配一個換行符。匹配一個製表符, 等 |
\1...\9 | 匹配第n個分組的內容。 |
\10 | 匹配第n個分組的內容,如果它經匹配。否則指的是八進位制字元碼的表示式。 |