<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
正規表示式一直是被我所忽略的東西,因為在之前的學習和開發中基本很少用到它。而且,之前學習正規表示式時感覺很懵逼,所以毅然決然的放棄了(QAQ),然而出來混總歸還是要還的。最近在弄紀錄檔處理時,必須用到正規表示式,這就讓我不得不拿起正規表示式了。在此記錄一些自己學習的筆記與案例。
在python中匯入re包
import re
嘗試從字串 開始 位置(看清楚,開始位置!!!)匹配一個模式。成功則返回一個match物件,失敗則是none
引數說明:
pattern
:正規表示式string
:字串flags
:可選標誌位注:可選標誌在下面簡單說明
獲取物件的方法:
使用group(num) 來獲取物件小組內的內容。
舉例:
#_*_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 110
match()方法最重要的一點就是它是從字串開始匹配的,切記這一點······我已經在這點上犯了很多錯誤了。
在寫簡單的正規表示式的時候我們可以用()來進行分組,以便於我們在後續處理中取值。後續也會談到通過命名捕獲的方式來取值。
跟match函數引數一樣,它也是用來匹配字串的。而最大的不同在於它可以從字串的任意位置匹配,不像match一樣,僅限於從字串開始位置。引數跟match一樣,就不做說明了,直接上例子。
#與match例子不同,001前面有很多空格 str1=' 001-010-110' #與match中的模式一樣 pattern = r'd{3}-d{3}-d{3}' #若此時用match()函數,結果肯定是不匹配的。 search = re.search(pattern,str1) print search.group() print search.group(0) print search.group(1) print search.group(2) print search.group(3) #結果: 001-010-110 001-010-110 001 010 110
對於match和search,還是得說一遍,注意一個必須是從字串開始處匹配,一個是任意位置。
用於替換字串中的匹配項
re.sub(pattern,repl,string,count,flags)
引數說明:
pattern
:正規表示式repl
:替換的字串,可為一個函數string
:要被查詢的原始字串count
:被替換的次數,預設替換所有匹配項flags
:標誌位 #_*_coding:utf-8_*_ import re phone = "888-7777-6666 #好牛的號碼 #刪除字串中的註釋 num = re.sub(r'#.*','',phone) print num #刪除註釋和- realphone = re.sub(r'D','',phone) print realphone #結果為: 888-7777-6666 88877776666
sub函數理解起來不難,但要主要的是在repl引數的使用。repl可以為一個函數。例如:
將字串中的數位乘以二
def double(match): value = int(match.group('value')) return str(value*2) s='APPLE23EFG567' print re.sub(r'(?P<value>d+)',double,s) #結果為: APPLE46EFG1134
因為repl為一個函數,所以再替換的時候會替換為函數的返回值。
注:?P<value>為正規表示式的命名捕獲,在下面將會做簡單記錄
格式為: ?P<name>
在處理字串取值時往往會用到
例子:
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
在上述例子要分別獲取每項的值就要使用group(num),而當正規表示式變得複雜的時候,再用num取值時,很有可能會取到錯誤的值。所以就提出使用命名捕獲,下面為簡單例子:
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
雖然在上述例子中使用命名捕獲會將降低正規表示式的可讀性,但命名捕獲咋複雜的正則中,會準確獲取想要的值(當然,正則肯定得寫準確啊·····)
前提假設:
正規表示式的強大已不用我贅述,Python 對此的支援也是十分強大,只不過:
re.search(pattern, string, flags=0) re.match(pattern, string, flags=0) ......
你能很麻利地使用如上所示的一系列模組級別function 嗎,如果你天天用 Python 搞正則匹配,相信你一定很熟練。但是如果你需要每次臨時翻閱檔案才能知道如何使用它,那麼就要思考:是不是 API 在某種程度上設計不好了(有的語言的 pattern 極有可能不是放在首位)。
一般來說,API 的介面引數越少越好,最好的就是沒有引數,呼叫者無腦呼叫,沒有任何記憶負擔。而 Python 的 re 庫,在我看來,應該至少糅合了「命令式」與「OOP」兩種風格,而且介面也不「最小化,正交」。
正確的姿勢應該是:只用 OOP 風格,並且完全忘記 re 庫提供的一系列模組級別的 function (如 re.search, re.match等)。
首先是每次都構造出 Regex 物件,然後由 Regex 物件得出 Match 物件,然後在 Regex 物件和 Match 物件上進行一系列操作。比如:
# 1. 構造 REGEX = re.compile($pattern, flags) flags是re模組的常數 # 2. 獲取 MatchObject m = regex.search(string) # 3. 後續 MatchObject 的使用 1. 獲取分組 group() 2. groups 3. groupdict()
比如我在自己構造的 PathUtils 中,就是如此使用的(我非常喜歡各種各樣的 Utils ):
from __future__ import (absolute_import, unicode_literals) import re class PathUtils(object): """路徑操作的工具函數""" _LINUX_ROOT = '/' _LINUX_PATH_SPLITOR = '/' @classmethod def is_two_linux_path_contains(cls, path1, path2): """兩個Linux路徑是否存在互相包含關係""" 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
主要的功能函數就是:
@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
這樣一系列流程下來,我的感受就是,re 庫的介面沒有需要記憶,也沒有需要臨時翻閱檔案的地方,並且我只用這一種風格(自己熟悉的,效率總是最高的),比如 re.compile肯定只需要傳一個引數(flags不是必要的),REGEX_OBJ.match/search肯定只需要傳need_search_string即可。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45