正则有关模块
本篇不会过多介绍正则表达式内容,可参考 js 篇的正则对象章节。
正则表达式
python 不支持不定长的后行断言(逆序环视)
error: look-behind requires fixed-width pattern
正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法。或者说:正则就是用来描述一类事物的规则。(在 Python 中)它内嵌在 Python 中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。
正则表达式 | 类型 | 匹配内容 |
---|---|---|
. | 元字符 | 匹配除换行符以外的任意字符 |
\w | 元字符 | 匹配字母或数字或下划线,大写即非数字字母下划线 |
\s | 元字符 | 匹配任意的空白符,大写即非空字符 |
\d | 元字符 | 匹配数字,大写即非数字 |
\n | 元字符 | 匹配一个换行符,也属于\s |
\t | 元字符 | 匹配一个制表符,也属于\s |
\b | 元字符 | 匹配一个单词的边界 |
^ | 元字符 | 匹配字符串的开始 |
$ | 元字符 | 匹配字符串的结尾 |
`a | b` | 逻辑 |
(...) | 分组 | 匹配括号内的组,捕获 |
(?:...) | 分组 | 匹配括号内的组,不捕获 |
(?<Name>...) | 命名分组 | 匹配括号内的组,捕获并命名(python 支持) |
(?>...) | 固化分组 | 匹配过程中不交还括号内的组(python 不支持) |
[...] | 字符集 | 匹配字符组中的字符 |
[^...] | 字符集 | 匹配除了字符组中字符的所有字符 |
* | 量词 | 贪婪匹配,重复零次或更多次 |
+ | 量词 | 贪婪匹配,重复一次或更多次 |
? | 量词 | 贪婪匹配,重复零次或一次 |
{n} | 量词 | 重复 n 次 |
{n,} | 量词 | 重复 n 次或更多次 |
{n,m} | 量词 | 重复 n 到 m 次 |
(?=pattern) | 断言 | 后面有,断言也叫环视 look-behind |
(?!pattern) | 断言 | 后面没有 |
(?<=pattern) | 断言 | 前面有(python 不支持不定长逆序环视) |
(?<!pattern) | 断言 | 前面没有(python 不支持不定长逆序环视) |
注意
- python 中正则表达式是不是真实字符串,需要二重转义,推荐使用真实字符串(
r""
) - 贪婪匹配会尽可能匹配,后面加?号使其变成惰性匹配,匹配尽可能少的。
- 断言(环视)的括号中的匹配到的内容只会用来判断不会被正则表达式捕获。
- 由于状态机制,从左往右被捕获的字符不再参与匹配。例如'ababa'里无法捕获到第二个'aba'
常用范围
正则 | 说明 |
---|---|
[0-9] | 和[0123456789] 和\d 是一个意思 |
[a-z]+ | 不定长的小写字母,尽可能多,一个以上 |
[A-Z]*? | 不定长的大写字母,尽可能少,可以一个都没有 |
[0-9a-fA-F] | 十六进制字符 |
`^.*(?=.jpg$ | .png)` |
^(?!-).* | 不以- 开头的行(re.M 模式) |
[a-z0-9_\.-]{3,15}@[a-z]{2,5}\.[a-z]{2,6} |
re 模块
re
模块提供了与 Perl 语言类似的正则表达式匹配操作
最常用方法
re.findall(r,txt)
查找所有满足匹配条件的结果,放在列表里re.match(r,txt)
匹配第一个然后返回一个包含匹配信息的对象re.sub(r,s,txt)
将所有满足匹配条件的替换成字符串 s
模式flags
不同模式主要会改变.
以及^
和$
的匹配行为
None
首行模式,默认的。只有第一行都有开头和结尾。换行符不会被匹配。re.S
/re.DOTALL
单行模式,整个文本看成一行。换行符会被当作普通字符匹配。re.M
/re.MULTILINE
多行模式,每一行都有开头和结尾。换行符不会被匹配。re.I
/re.IGNORECASE
忽略大小写模式。
多模式可以直接相加
shell
s = '''few.JPG
oij.png
ade.jpg
ade.jpg.rename
ytr.GIF
pow.PNG'''
>>> re.findall(r'.*(?=\.jpg|\.png)', s)
['oij', '', 'ade', '', 'ade', '']
>>> re.findall(r'^.*(?=\.jpg$|\.png$)', s, re.M+re.I)
['few', 'oij', 'ade', 'pow']
分组(...)
分组在某种程度上完全可以代替断言的功能。
shell
>>> re.findall('(.*?)_sb', 'alex_sb wusir_sb 日天_sb')
['alex', 'wusir', '日天']
>>> HTML = '<a href="http://www.baidu.com">点击</a>'
>>> print(re.findall('href="(.*?)"', HTML))
['http://www.baidu.com']
分组()
中加入?:
表示整体,而不是只针对性捕获()
里面的内容。
python
import re
ret = re.findall("www.(baidu|oldboy).com", "www.oldboy.com")
print(
ret
) # ['oldboy']这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可
ret = re.findall("www.(?:baidu|oldboy).com", "www.oldboy.com")
print(ret) # ['www.oldboy.com']
常用方法用例
python
import re
ret = re.findall("a", "eva egon yuan") # 返回所有匹配的字符串,放在列表里
print(ret) # 结果 : ['a', 'a']
ret = re.search("a", "eva egon yuan").group()
print(ret) # 结果 : 'a'
# 返回匹配成功的第一个Match对象,找不到则是None
# Match对象的group()方法得到匹配的字符串
ret = re.match("a", "abc").group() # 从头开始匹配 相当于search('^a', 'abc').group()
print(ret) # 结果 : 'a'
ret = re.split("[ab]", "abcd") # 先按'a'分割得到''和'bcd',再对''和'bcd'分别按'b'分割
print(ret) # ['', '', 'cd']
ret = re.sub("\d", "H", "eva3egon4yuan4", 1) # 简单的匹配后替换,参数1表示只替换1个
print(ret) # evaHegon4yuan4
ret = re.subn(
"\d", "H", "eva3egon4yuan4"
) # 匹配后替换,返回元组(替换的结果,替换了多少次)
print(ret)
obj = re.compile("\d{3}") # 将正则表达式编译成为一个Pattern对象,这里匹配的是3个数字
ret = obj.search("abc123eeee") # Pattern对象调用search,参数为待匹配的字符串
print(ret.group()) # 结果 : 123
ret = re.finditer("\d", "ds3sy4784a") # finditer返回一个存放Match对象的迭代器
print(next(ret).group()) # 查看第一个的结果
print(next(ret).start()) # 查看第二个在原字符串里面的开始的位置
print([i.group() for i in ret]) # 查看剩余的结果
注意:
- 多行模式(
MULTILINE
)中match()
只匹配字符串的开始,但search()
和以'^'
开头的正则会每行匹配 split()
的优先级查询
python
ret = re.split("\d+", "eva3egon4yuan")
print(ret) # 结果 : ['eva', 'egon', 'yuan']
ret = re.split("(\d+)", "eva3egon4yuan")
print(ret) # 结果 : ['eva', '3', 'egon', '4', 'yuan']
在匹配部分加上()
之后所切出的结果是不同的, 没有()
的没有保留所匹配的项,但是有()
的却能够保留了匹配的项, 这个在某些需要保留匹配部分的使用过程是非常重要的。
.sub()
第二个参数可以接受函数 第一个参数要使用分组(命名分组)
python
size = "height165weight21deep213" # 要求所有数字内容都加5
re.sub(r"(?P<num>\d+)", lambda x: str(int(x.group("num")) + 5), size)
# 'height170weight26deep218'
regex 模块
Python 自带了正则表达式引擎(内置的 re 模块),但是不支持一些高级特性,比如下面这几个:
- 固化分组 Atomic grouping
- 占有优先量词 Possessive quantifiers
- 可变长度的逆序环视 Variable-length lookbehind
- 递归匹配 Recursive patterns
- (起始/继续)位置锚\G Search anchor
第三方模块 regex 实现了如上高级特效,且 API 与 re 模块一致。