Python re模塊與正則表達式詳解
問題:
匹配字符串,最少以3個數字開頭。使用Python代碼如何實現?
檢查條件:
1>字符串長度判斷;
2>判斷前三個字符是否是數字;
這樣實現起來有點啰嗦,我們可以使用正則表達式,先來看正則表達式基本語法。
1 正則表達式基本語法
. 匹配任意字符(不包括換行符) ^ 匹配開始位置,多行模式下匹配每一行的開始 $ 匹配結束位置,多行模式下匹配每一行的結束 * 匹配前一個元字符0到多次 + 匹配前一個元字符1到多次 ? 匹配前一個元字符0到1次 {m,n} 匹配前一個元字符m到n次 \ 轉義字符,例如\.只能匹配. [] 字符集,一個字符的集合,可匹配其中任意一個字符 \d 匹配一個數字, 相當於 [0-9] \D 匹配非數字,相當於 [^0-9] \s 匹配任意空白字符, 相當於 [ \t\n\r\f\v] \S 匹配非空白字符,相當於 [^ \t\n\r\f\v] \w 匹配數字、字母、下劃線中任意一個字符, 相當於 [a-zA-Z0-9_] \W 匹配非數字、字母、下劃線中的任意字符,相當於 [^a-zA-Z0-9_] | 邏輯表達式 或 ,比如 a|b 代表可匹配 a 或者 b (...) 分組
給一坨這個玩意,怎麽用,都需要記住嗎?
如果能記住就記住,如果很久不使用,就忘記吧;
等使用的時候直接查資料,理解能使用即可。
下面我們結合re模塊,看正則表達式如何使用。
2 re.compile方法;
Python中正則表達式執行過程:根據表達式編譯生成Pattern對象,然後進行相關處理;
如果高頻率使用一個固定的正則表達式,我們可以提前生成Pattern對象,提高效率。
compile方法:
import re
re.compile(pattern, flags=0) #pattern為正則表達式
參數:
pattern:正則表達式,是指為字符串;為了防止轉義推薦使用原字符串(r‘xxx‘);
flags:編譯標誌位,修改正則表達式的匹配方式,例如:大小寫區分,換行處理等;
例子:匹配任意一個數字開頭字符串:
import re
pobj = re.compile(r‘\d‘)
type(pobj)
輸出結果:re.Pattern對象;
問題:如何來匹配呢?
3 re.match方法
re.match方法:從起始位置開始匹配,返回None或者re.Match對象;
#re模塊match方法,參數:pattern:正則表達式,string:處理字符串 re.match(pattern, string, flags=0) #re.Pattern對象中match方法,參數:string:處理字符串 re.Pattern.match(string, pos=0, endpos=...)
練習:匹配一個數字開頭字符串:
import re
ma = re.match(r‘\d‘, ‘123‘)
print(ma)
輸出結果:
<re.Match object; span=(0, 1), match=‘1‘>
match方法匹配過程:生成Pattern對象,然後進行匹配;
如何獲取匹配結果?來看Match對象相關方法。
方法 | 說明 | |
---|---|---|
ma.end(group=0, /) | 返回指定分組的結束位置 | |
ma.start(group=0, /) | 返回指定分組的開始位置 | |
ma.span(group=0, /) | 返回指定分組開始與結束位置 | |
ma.group([group1, ...]) | 返回字符串或者元組 | |
ma.groups(default=None) | 返回所有分組信息 | |
groupdict([default=None]) | 根據key獲取分組信息 |
實際操作下,理解起來就容易了:
import re
import re
#正則表達式:匹配內容:數字+a~z+數字,並且進行分組
ma = re.match(r‘(\d)\w*(\d)‘, ‘1c3‘)
#匹配結果:‘1c3‘
print(‘group():‘, ma.group())
#獲取指定分組:1
print(‘group(1):‘, ma.group(1))
#獲取多個分組:(‘1‘, ‘3‘)
print(‘group(1,2):‘, ma.group(1,2))
#獲取所有分組:(‘1‘, ‘3‘)
print(‘groups():‘, ma.groups())
#獲取匹配結果索引:(0, 3)
print(‘span():‘, ma.span())
#獲取指定分組索引:(0, 1)
print(‘span(1):‘,ma.span(1))
輸出結果:
group(): 1c3
group(1): 1
group(1,2): (‘1‘, ‘3‘)
groups(): (‘1‘, ‘3‘)
span(): (0, 3)
span(1): (0, 1)
match方法只能用於從頭匹配,如何在整個字符串中查找?
使用search方法。
4:re.search方法
search方法用於在字符串中查找,返回Match對象或者None;
search(pattern, string, flags=0);參數與match類似。
練習:查找第一次出現的數字組成的字串,例如:
在字符串:‘pay:2000 date:2019-03-04‘,找到支付價格:2000;
分析:
1>支付前固定值:‘pay:‘
2>支付金額:數字字符串
對應正則表達式邏輯:‘pay:‘+匹配數字直到非數字字符;具體實現:
s = ‘pay:2000 date:2019-03-04‘
#\d+:匹配數字一次或者多次
ma = re.search(r‘pay:\d+‘, s)
print(ma)
輸出結果:
<re.Match object; span=(0, 8), match=‘pay:2000‘>
如何獲取2000這個值?增加一個分組,代碼實現:
s = ‘pay:2000 date:2019-03-04‘
#\d+:匹配數字一次或者多次,使用分組
ma = re.search(r‘pay:(\d+)‘, s)
print(ma)
#獲取分組1對應值
print(ma.group(1))
輸出結果:
<re.Match object; span=(0, 8), match=‘pay:2000‘>
2000
5 re.findall/finditer方法
re.findall:在字符串中根據正則表達式查找所有匹配,返回查找結果組成列表;
re.finditer與findall功能相同,返回自叠代器;
re.findall(pattern, string, flags=0)
練習:查找字符串中所有數字字符串,
例如:‘pay:2000 date:2019-03-04‘ 查找數字結果:[‘2000‘, ‘2019‘, ‘03‘, ‘04‘]
實現如下:
import re
s = ‘pay:2000 date:2019-03-04‘
result = re.findall(r‘\d+‘, s)
print(result)
結果為列表:[‘2000‘, ‘2019‘, ‘03‘, ‘04‘];
6 re.split方法
re.split:字符串中根據正則表達式查找匹配字符串,然後進行切分,返回字串列表;
re.split(pattern, string, maxsplit=0, flags=0)
#maxsplit:切分次數,默認所有匹配都切分
練習:
info = ‘system:linux, cpu:x64 memory 8G‘
整理格式:
dinfo = {‘system‘:‘linux‘, ‘cpu‘:‘x64‘, ‘memory‘:‘8G‘}
分析:
1>對info使用非字母,數字進行切分;
2>切分後將其整理成字典;
第一步切分:
info = ‘system:linux, cpu:x64 memory 8G‘
#正則表達式:\W+,匹配1個或多個
s = re.split(r‘\W+‘,info)
print(s)
切分結果:[‘system‘, ‘linux‘, ‘cpu‘, ‘x64‘, ‘memory‘, ‘8G‘];
第二步整理字典:
info = ‘system:linux, cpu:x64 memory 8G‘
s = re.split(r‘\W+‘,info)
dinfo = {}
for index in range(0, len(s), 2):
dinfo[s[index]] = s[index+1]
print(dinfo)
輸出結果:{‘system‘: ‘linux‘, ‘cpu‘: ‘x64‘, ‘memory‘: ‘8G‘}
7 re.sub與re.subn
re.sub與re.subn實現的字符串替換功能;
re.sub(pattern, repl, string, count=0, flags=0)
re.subn(pattern, repl, string, count=0, flags=0)
re.sub方法根據正則表達式將匹配子串替換成設置值並返回新字符串;參數如下:
主要參數 | 說明 |
---|---|
pattern | 正則表達式 |
repl | 替換內容,可以是字符串或者函數 |
string | 處理字符串 |
count | 替換數量 |
re.subn與re.sub類似,返回替換數量與新字符串;
練習:
s = "user:sun,pwd:222222",將密碼:222222 替換為:******;
可以直接使用字符串替換方法:
s.replace(‘222222‘, ‘******‘)
#結果:‘user:sun,pwd:******‘
如果密碼為不一樣數字如何替換?例如:
s = "user:sun,pwd:234567"
使用re.sub方法:
#將pwd:xxxx替換成******
re.sub(r‘pwd:(\d+)‘, "******", s)
#結果:‘user:sun,******‘
問題:pwd:去哪裏了?如何處理?使用分組。
#pattern使用兩個分組
#repl為原字符串,\1代表第一個分組內容,
re.sub(r‘(pwd:)(\d+)‘, r"\1******", s)
替換結果:
‘user:sun,pwd:******‘
大家可以理解下這個題目。
新的問題來了,一組考試成績:
s = ‘math:90, chinese:90, english:50‘
大於等於60,替換成Pass,否則替換成Faild;推薦使用正則。
我們可以使用函數功能,先來看匹配分數,將其替換為空字符串;
re.sub(r‘\d+‘, ‘‘, s)
結果:‘math:, chinese:, english:‘;
我們將repl替換成函數,函數有一個參數,返回值為空字符串;
def func(arg):
print(arg)
return ‘‘
re.sub(r‘\d+‘, func, s)
輸出結果:
<_sre.SRE_Match object; span=(5, 7), match=‘90‘>
<_sre.SRE_Match object; span=(17, 19), match=‘90‘>
<_sre.SRE_Match object; span=(29, 31), match=‘50‘>
‘math:, chinese:, english:‘
可以看到func中參數為每個匹配的match對象,我們可以獲取這個值,並對其處理。
def func(arg):
#獲取分數
score = int(arg.group())
#重置返回結果
if score <60:
return ‘Faild‘
return ‘Pass‘
re.sub(r‘\d+‘, func, s)
輸出結果:
‘math:Pass, chinese:Pass, english:Faild‘
以上這些就是re模塊常用使用方法及正則表達式基本語法,後面文章我們在介紹正則表達式更高級使用。
Python re模塊與正則表達式詳解