Skip to content

正则有关模块

本篇不会过多介绍正则表达式内容,可参考 js 篇的正则对象章节。

正则表达式

python 不支持不定长的后行断言(逆序环视)

error: look-behind requires fixed-width pattern

正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法。或者说:正则就是用来描述一类事物的规则。(在 Python 中)它内嵌在 Python 中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。

正则表达式类型匹配内容
.元字符匹配除换行符以外的任意字符
\w元字符匹配字母或数字或下划线,大写即非数字字母下划线
\s元字符匹配任意的空白符,大写即非空字符
\d元字符匹配数字,大写即非数字
\n元字符匹配一个换行符,也属于\s
\t元字符匹配一个制表符,也属于\s
\b元字符匹配一个单词的边界
^元字符匹配字符串的开始
$元字符匹配字符串的结尾
`ab`逻辑
(...)分组匹配括号内的组,捕获
(?:...)分组匹配括号内的组,不捕获
(?<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}Email

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 模块一致。