python中對(duì)正則表達(dá)式re包的簡(jiǎn)單引用方式
對(duì)正則表達(dá)式re包的簡(jiǎn)單引用
正則表達(dá)式一直是被我所忽略的東西,因?yàn)樵谥暗膶W(xué)習(xí)和開(kāi)發(fā)中基本很少用到它。而且,之前學(xué)習(xí)正則表達(dá)式時(shí)感覺(jué)很懵逼,所以毅然決然的放棄了(QAQ),然而出來(lái)混總歸還是要還的。最近在弄日志處理時(shí),必須用到正則表達(dá)式,這就讓我不得不拿起正則表達(dá)式了。在此記錄一些自己學(xué)習(xí)的筆記與案例。
在python中導(dǎo)入re包
import re ?
一、re.match(pattern,string,flags=0)
嘗試從字符串 開(kāi)始 位置(看清楚,開(kāi)始位置?。。。┢ヅ湟粋€(gè)模式。成功則返回一個(gè)match對(duì)象,失敗則是none
參數(shù)說(shuō)明:
pattern:正則表達(dá)式string:字符串flags:可選標(biāo)志位
注:可選標(biāo)志在下面簡(jiǎn)單說(shuō)明
獲取對(duì)象的方法:
使用group(num) 來(lái)獲取對(duì)象小組內(nèi)的內(nèi)容。
舉例:
#_*_coding:utf8_*_
import re
str1='010-011-110'
pattern = r'\d{3}-\d{3}-\d{3}'
match = re.match(pattern,str1)
print match.group()
print match.group(0)
print match.group(1)
print match.group(2)
print match.group(3)
#輸出為:
010-011-110
010-011-110
010
011
110match()方法最重要的一點(diǎn)就是它是從字符串開(kāi)始匹配的,切記這一點(diǎn)······我已經(jīng)在這點(diǎn)上犯了很多錯(cuò)誤了。
在寫(xiě)簡(jiǎn)單的正則表達(dá)式的時(shí)候我們可以用()來(lái)進(jìn)行分組,以便于我們?cè)诤罄m(xù)處理中取值。后續(xù)也會(huì)談到通過(guò)命名捕獲的方式來(lái)取值。
二、re.search(pattern,string,flags=0)
跟match函數(shù)參數(shù)一樣,它也是用來(lái)匹配字符串的。而最大的不同在于它可以從字符串的任意位置匹配,不像match一樣,僅限于從字符串開(kāi)始位置。參數(shù)跟match一樣,就不做說(shuō)明了,直接上例子。
#與match例子不同,001前面有很多空格
str1=' 001-010-110'
#與match中的模式一樣
pattern = r'\d{3}-\d{3}-\d{3}'
#若此時(shí)用match()函數(shù),結(jié)果肯定是不匹配的。
search = re.search(pattern,str1)
print search.group()
print search.group(0)
print search.group(1)
print search.group(2)
print search.group(3)
#結(jié)果:
001-010-110
001-010-110
001
010
110對(duì)于match和search,還是得說(shuō)一遍,注意一個(gè)必須是從字符串開(kāi)始處匹配,一個(gè)是任意位置。
三、檢索和替換 re.sub()
用于替換字符串中的匹配項(xiàng)
re.sub(pattern,repl,string,count,flags)
參數(shù)說(shuō)明:
pattern:正則表達(dá)式repl:替換的字符串,可為一個(gè)函數(shù)string:要被查找的原始字符串count:被替換的次數(shù),默認(rèn)替換所有匹配項(xiàng)flags:標(biāo)志位
#_*_coding:utf-8_*_ import re phone = "888-7777-6666 #好牛的號(hào)碼 #刪除字符串中的注釋 num = re.sub(r'#.*','',phone) print num #刪除注釋和- realphone = re.sub(r'\D','',phone) print realphone #結(jié)果為: 888-7777-6666 88877776666
sub函數(shù)理解起來(lái)不難,但要主要的是在repl參數(shù)的使用。repl可以為一個(gè)函數(shù)。例如:
將字符串中的數(shù)字乘以二
def double(match):
? ? value = int(match.group('value'))
? ? return str(value*2)
s='APPLE23EFG567'
print re.sub(r'(?P<value>\d+)',double,s)
?
#結(jié)果為:
?APPLE46EFG1134因?yàn)閞epl為一個(gè)函數(shù),所以再替換的時(shí)候會(huì)替換為函數(shù)的返回值。
注:?P<value>為正則表達(dá)式的命名捕獲,在下面將會(huì)做簡(jiǎn)單記錄
四、正則表達(dá)式之命名捕獲
格式為: ?P<name>
在處理字符串取值時(shí)往往會(huì)用到
例子:
num = '001-010-110'
pattern = r'(\d{3})-(\d{3})-(\d{3})'
match = re.match(pattern,num)
print match.group() #001-010-110
print match.group(1) #001
print match.group(2) #010
print match.group(3) #110在上述例子要分別獲取每項(xiàng)的值就要使用group(num),而當(dāng)正則表達(dá)式變得復(fù)雜的時(shí)候,再用num取值時(shí),很有可能會(huì)取到錯(cuò)誤的值。所以就提出使用命名捕獲,下面為簡(jiǎn)單例子:
pattern = r'(?P<Area>\d{3})-(?P<zhong>\d{3})-(?P<wei>\d{3})'
match = re.match(patter, num)
?
print match.group('Area') ? ? #001
print match.group('zhong') ? ?#010
print match/group('wei') ? ? ?#110雖然在上述例子中使用命名捕獲會(huì)將降低正則表達(dá)式的可讀性,但命名捕獲咋復(fù)雜的正則中,會(huì)準(zhǔn)確獲取想要的值(當(dāng)然,正則肯定得寫(xiě)準(zhǔn)確啊·····)
re庫(kù)的正確使用姿勢(shì)
前提假設(shè):
- 已經(jīng)充分掌握PCRE風(fēng)格正則表達(dá)式
- 熟讀re庫(kù)文檔
Why
正則表達(dá)式的強(qiáng)大已不用我贅述,Python 對(duì)此的支持也是十分強(qiáng)大,只不過(guò):
re.search(pattern, string, flags=0) re.match(pattern, string, flags=0) ......
你能很麻利地使用如上所示的一系列模塊級(jí)別function 嗎,如果你天天用 Python 搞正則匹配,相信你一定很熟練。但是如果你需要每次臨時(shí)翻閱文檔才能知道如何使用它,那么就要思考:是不是 API 在某種程度上設(shè)計(jì)不好了(有的語(yǔ)言的 pattern 極有可能不是放在首位)。
一般來(lái)說(shuō),API 的接口參數(shù)越少越好,最好的就是沒(méi)有參數(shù),調(diào)用者無(wú)腦調(diào)用,沒(méi)有任何記憶負(fù)擔(dān)。而 Python 的 re 庫(kù),在我看來(lái),應(yīng)該至少糅合了「命令式」與「OOP」兩種風(fēng)格,而且接口也不「最小化,正交」。
使用姿勢(shì)
正確的姿勢(shì)應(yīng)該是:只用 OOP 風(fēng)格,并且完全忘記 re 庫(kù)提供的一系列模塊級(jí)別的 function (如 re.search, re.match等)。
首先是每次都構(gòu)造出 Regex 對(duì)象,然后由 Regex 對(duì)象得出 Match 對(duì)象,然后在 Regex 對(duì)象和 Match 對(duì)象上進(jìn)行一系列操作。比如:
# 1. 構(gòu)造
REGEX = re.compile($pattern, flags) flags是re模塊的常量
# 2. 獲取 MatchObject
m = regex.search(string)
# 3. 后續(xù) MatchObject 的使用
1. 獲取分組 group()
2. groups
3. groupdict()應(yīng)用舉例
比如我在自己構(gòu)造的 PathUtils 中,就是如此使用的(我非常喜歡各種各樣的 Utils ):
from __future__ import (absolute_import, unicode_literals)
import re
class PathUtils(object):
"""路徑操作的工具函數(shù)"""
_LINUX_ROOT = '/'
_LINUX_PATH_SPLITOR = '/'
@classmethod
def is_two_linux_path_contains(cls, path1, path2):
"""兩個(gè)Linux路徑是否存在互相包含關(guān)系"""
if path1 == cls._LINUX_ROOT or path2 == cls._LINUX_ROOT:
return True
path1_split = path1.split(cls._LINUX_PATH_SPLITOR)
path2_split = path2.split(cls._LINUX_PATH_SPLITOR)
for item1, item2 in zip(path1_split, path2_split):
if item1 != item2:
return False
return True
@classmethod
def is_valid_linux_path(cls, path):
if not path:
return False
LINUX_PATH_REGEX = r'^(/[^/ ]*)+/?$'
return cls.is_valid_pattern(path, LINUX_PATH_REGEX)
@classmethod
def is_valid_windows_path(cls, path):
if not path:
return False
WINDOWS_PATH_REGEX = r'^[a-zA-Z]:\\(((?![<>:"/\\|?*]).)+((?<![ .])\\)?)*$'
return cls.is_valid_pattern(path, WINDOWS_PATH_REGEX)
@classmethod
def is_valid_path(cls, p):
if not p:
return False
return cls.is_valid_linux_path(p) or cls.is_valid_windows_path(p)
@classmethod
def is_valid_pattern(cls, value, pattern):
if not value:
return False
REGEX = re.compile(pattern, re.UNICODE)
m = REGEX.match(value)
return True if m else False
主要的功能函數(shù)就是:
@classmethod def is_valid_pattern(cls, value, pattern): ? ? if not value: ? ? ? ? return False? ? ? REGEX = re.compile(pattern, re.UNICODE)? ? ? m = REGEX.match(value)? ? ? return True if m else False
這樣一系列流程下來(lái),我的感受就是,re 庫(kù)的接口沒(méi)有需要記憶,也沒(méi)有需要臨時(shí)翻閱文檔的地方,并且我只用這一種風(fēng)格(自己熟悉的,效率總是最高的),比如 re.compile肯定只需要傳一個(gè)參數(shù)(flags不是必要的),REGEX_OBJ.match/search肯定只需要傳need_search_string即可。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python使用matplotlib繪圖無(wú)法顯示中文問(wèn)題的解決方法
這篇文章主要介紹了Python使用matplotlib繪圖無(wú)法顯示中文問(wèn)題的解決方法,結(jié)合具體實(shí)例形式分析了Python使用matplotlib繪圖時(shí)出現(xiàn)中文亂碼的原因與相關(guān)解決方法,需要的朋友可以參考下2018-03-03
Python os.mkdir()與os.makedirs()的使用區(qū)別
這篇文章主要介紹了Python os.mkdir()與os.makedirs()的使用區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-03-03
淺談Python實(shí)現(xiàn)opencv之圖片色素的數(shù)值運(yùn)算和邏輯運(yùn)算
今天帶大家來(lái)學(xué)習(xí)的是關(guān)于Python的相關(guān)知識(shí),文章圍繞著圖片色素的數(shù)值運(yùn)算和邏輯運(yùn)算展開(kāi),文中有非常詳細(xì)的的介紹及代碼示例,需要的朋友可以參考下2021-06-06
Python數(shù)學(xué)建模學(xué)習(xí)模擬退火算法多變量函數(shù)優(yōu)化示例解析
模擬退火算法借鑒了統(tǒng)計(jì)物理學(xué)的思想,是一種簡(jiǎn)單、通用的啟發(fā)式優(yōu)化算法,并在理論上具有概率性全局優(yōu)化性能,因而在科研和工程中得到了廣泛的應(yīng)用2021-10-10
python爬蟲(chóng)之請(qǐng)求模塊urllib的基本使用
urllib是python內(nèi)置的HTTP請(qǐng)求庫(kù),是一個(gè)用來(lái)處理網(wǎng)絡(luò)請(qǐng)求的python標(biāo)準(zhǔn)庫(kù),下面這篇文章主要給大家介紹了關(guān)于python爬蟲(chóng)之請(qǐng)求模塊urllib的基本使用,需要的朋友可以參考下2022-04-04
Python中的正則表達(dá)式與JSON數(shù)據(jù)交換格式
正則表達(dá)式 是一個(gè)特殊的字符序列,一個(gè)字符串是否與我們所設(shè)定的這樣的字符序列,相匹配快速檢索文本、實(shí)現(xiàn)替換文本的操作。這篇文章主要介紹了Python中的正則表達(dá)式與JSON ,需要的朋友可以參考下2019-07-07
Python數(shù)據(jù)分析與機(jī)器學(xué)習(xí)在金融風(fēng)控中的應(yīng)用小結(jié)
本篇詳解了Python數(shù)據(jù)分析與機(jī)器學(xué)習(xí)在金融風(fēng)控中的應(yīng)用,包括數(shù)據(jù)收集與預(yù)處理、信用風(fēng)險(xiǎn)評(píng)估模型、市場(chǎng)風(fēng)險(xiǎn)管理模型和操作風(fēng)險(xiǎn)監(jiān)控模型,感興趣的朋友跟隨小編一起看看吧2024-06-06

