Python re 库的正确使用姿势

 2023-09-05 阅读 227 评论 0

摘要:前提假设: 已经充分掌握 PCRE 风格正则表达式熟读 re 库文档Why 正则表达式的强大已不用我赘述,Python 对此的支持也是十分强大,只不过: re.search(pattern, string, flags=0) re.match(pattern, string, flags=0) ...... 复制代码你能很麻利地使

前提假设:

  1. 已经充分掌握 PCRE 风格正则表达式
  2. 熟读 re 库文档

Why

正则表达式的强大已不用我赘述,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. 获取 MatchObjectm = regex.search(string)# 3. 后续 MatchObject 的使用1. 获取分组  group()    2. groups3. groupdict()
复制代码

应用举例

比如我在自己构造的 PathUtils 中,就是如此使用的(我非常喜欢各种各样的 Utils ):

from __future__ import (absolute_import, unicode_literals)import reclass PathUtils(object):"""路径操作的工具函数"""_LINUX_ROOT = '/'_LINUX_PATH_SPLITOR = '/'@classmethoddef is_two_linux_path_contains(cls, path1, path2):"""两个Linux路径是否存在互相包含关系"""if path1 == cls._LINUX_ROOT or path2 == cls._LINUX_ROOT:return Truepath1_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 Falsereturn True@classmethoddef is_valid_linux_path(cls, path):if not path:return FalseLINUX_PATH_REGEX = r'^(/[^/ ]*)+/?$'return cls.is_valid_pattern(path, LINUX_PATH_REGEX)@classmethoddef is_valid_windows_path(cls, path):if not path:return FalseWINDOWS_PATH_REGEX = r'^[a-zA-Z]:\\(((?![<>:"/\\|?*]).)+((?<![ .])\\)?)*$'return cls.is_valid_pattern(path, WINDOWS_PATH_REGEX)@classmethoddef is_valid_path(cls, p):if not p:return Falsereturn cls.is_valid_linux_path(p) or cls.is_valid_windows_path(p)@classmethoddef is_valid_pattern(cls, value, pattern):if not value:return FalseREGEX = 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 FalseREGEX = 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即可。

附录

  • re 库文档
  • PCRE 流派正则表达式风格

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/1/114.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息