前提假設:html
正則表達式的強大已不用我贅述,Python 對此的支持也是十分強大,只不過:python
re.search(pattern, string, flags=0)
re.match(pattern, string, flags=0)
......
複製代碼
你能很麻利地使用如上所示的一系列模塊級別function 嗎,若是你每天用 Python 搞正則匹配,相信你必定很熟練。可是若是你須要每次臨時翻閱文檔才能知道如何使用它,那麼就要思考:是否是 API 在某種程度上設計很差了(有的語言的 pattern 極有可能不是放在首位)。linux
通常來講,API 的接口參數越少越好,最好的就是沒有參數,調用者無腦調用,沒有任何記憶負擔。而 Python 的 re 庫,在我看來,應該至少糅合了「命令式」與「OOP」兩種風格,並且接口也不「最小化,正交」。正則表達式
正確的姿式應該是:只用 OOP 風格,而且徹底忘記 re 庫提供的一系列模塊級別的 function (如 re.search, re.match等)。windows
首先是每次都構造出 Regex 對象,而後由 Regex 對象得出 Match 對象,而後在 Regex 對象和 Match 對象上進行一系列操做。好比:bash
# 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
便可。ui