python中怎么对正则表达式re包进行引用
这篇文章主要介绍“python中怎么对正则表达式re包进行引用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“python中怎么对正则表达式re包进行引用”文章能帮助大家解决问题。
对正则表达式re包的简单引用
正则表达式一直是被我所忽略的东西,因为在之前的学习和开发中基本很少用到它。而且,之前学习正则表达式时感觉很懵逼,所以毅然决然的放弃了(QAQ),然而出来混总归还是要还的。最近在弄日志处理时,必须用到正则表达式,这就让我不得不拿起正则表达式了。在此记录一些自己学习的笔记与案例。
在python中导入re包
import re
一、re.match(pattern,string,flags=0)
尝试从字符串 开始 位置(看清楚,开始位置!!!)匹配一个模式。成功则返回一个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-110010-011-110010011110
match()方法最重要的一点就是它是从字符串开始匹配的,切记这一点······我已经在这点上犯了很多错误了。
在写简单的正则表达式的时候我们可以用()来进行分组,以便于我们在后续处理中取值。后续也会谈到通过命名捕获的方式来取值。
二、re.search(pattern,string,flags=0)
跟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-110001-010-110001010110
对于match和search,还是得说一遍,注意一个必须是从字符串开始处匹配,一个是任意位置。
三、检索和替换 re.sub()
用于替换字符串中的匹配项
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-666688877776666
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-110print match.group(1) #001print match.group(2) #010print 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') #001print match.group('zhong') #010print match/group('wei') #110
虽然在上述例子中使用命名捕获会将降低正则表达式的可读性,但命名捕获咋复杂的正则中,会准确获取想要的值(当然,正则肯定得写准确啊·····)
re库的正确使用姿势
前提假设:
已经充分掌握PCRE风格正则表达式
熟读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. 获取 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, path2, path3): """两个Linux路径是否存在互相包含关系""" if path2 == cls._LINUX_ROOT or path3 == cls._LINUX_ROOT: return True path2_split = path2.split(cls._LINUX_PATH_SPLITOR) path3_split = path3.split(cls._LINUX_PATH_SPLITOR) for item1, item2 in zip(path2_split, path3_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
主要的功能函数就是:
@classmethoddef 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即可。
关于“python中怎么对正则表达式re包进行引用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网行业资讯频道,小编每天都会为大家更新不同的知识点。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341