Python 正则表达式
python的正则表达式是在re模块,属于内置模块。正则表达式格式的详细说明见文章结束表, 模式的构建通过pattern= re.compile(regex_str, flag)构建,下面是python正则常用的函数。
python 正则函数 | 函数用法说明 |
---|---|
p= re.compile(regex_str, flag) | 正则模式构建 |
m = p.match(target_str) | str是否符合某种模式,从str开始位置进行扫描 |
m = p.search(target_str) | str是否包含某种模式的字符串,扫描整个字符串 |
上面返回的结果是一个match对象(匹配的结果放在其成员regs中,没有匹配特征m为空对象None),返回的结果可以通过m.group(idx)、m.groups()、m.groupdict()获取,从名字我们可以得知这是取分组的函数:
正则匹配结果 | 函数用法说明 |
---|---|
m.group(idx=0) | 整个正则字符串属于一个最大的分组,匹配的字符串默认放在下标为0的位置,整个字符串匹配的结果通过m.group() 正则表达式中()表示一个分组,正则字符串中的()匹配的结果通过m.group(idx)获取 |
m.groups() | 取正则字符串中括号分组匹配的所有结果,返回一个元组 |
m.groupdict() | 该功能需要与python独有的正则匹配规则配合使用 |
(1) match、search的区别:
>>> import re
>>> target_str = "Tom Cat"
>>> target_str2 = "***Tom--Tom Cat"
>>> p = re.compile(r"\w+ \w+")
# \w表示代码变量字符(字母数字下划线), + 表示匹配次数(1次或多次)
>>> m1 = p.match(target_str)
>>> s1 = p.search(target_str2)
>>>m1.group()
'Tom Cat'
>>>s1.group()
'Tom Cat'
>>>m1.groups()
()
(2) group()、groups()取分组值:
>>> import re
>>> target_str = "Tom Cat"
>>> p2 = re.compile(r"(\w+) (\w+)")
>>> m2 = p2.match(target_str)
>>> m2.group()
'Tom Cat'
>>> m2.group(1)
'Tom'
>>> m2.group(2)
'Cat'
>>> m2.groups()
('Tom', 'Cat')
>>> m2.gruopdict()
{}
(3) groupdicit()的使用:
先直接看一个例子,使得上面的正则匹配规则更有语义:
>>> import re
>>> target_str = "Tom Cat"
>>> p3 = re.compile(r"(?P<name>\w+) (?P<animal>\w+)")
>>> m3 = p3.match(target_str)
>>> m3.group()
'Tom Cat'
>>> m3.group('name')
'Tom'
>>> m3.group('animal')
'Cat'
>>> m2.groups()
('Tom', 'Cat')
>>> m2.gruopdict()
{'name': 'Tom', 'animal': 'Cat'}
python更有语义化的正则模式的构建(?P),下表中…代表正则模式字符串:
分组正则模式 | 功能说明 |
---|---|
(…) | 匹配括号内的任何正则表达式,并指示组的开始和结束。 要匹配括号本身(、),请使用\(或\),或将它们括在字符类内:[(],[)]。 |
(?P…) | 与普通括号类似,表示一个组;但通过组匹配的子字符串可以通过符号组名访问,注意: 组名必须是有效的Python标识符,并且每个组名只能在正则表达式中定义一次。 |
(?: …) | 普通括号的非捕获版本,匹配括号内的任何正则表达式,可以匹配0个或者多个 |
re.VERBOSE | 忽略换行,这个标志允许您通过可视化地分离模式的逻辑部分并添加注释, 来编写外观更好、可读性更好的正则表达式,非常适合和上述的正则模式搭配,是re.compile()的flag参数 |
一个werkzug路由的匹配实例:
_rule_re = re.compile(
r"""
(?P<static>[^<]*) # static rule data (1) # (a)
<
(?: # (b)
(?P<converter>[a-zA-Z_][a-zA-Z0-9_]*) # converter name (2)
(?:\((?P<args>.*?)\))? # converter arguments (3)
\: # variable delimiter (4)
)?
(?P<variable>[a-zA-Z_][a-zA-Z0-9_]*) # variable name (5) # (c)
>
""",
re.VERBOSE,
)
我们可以先来看一个完全匹配上面正则的实例:/doc/<string(length=2):lang_code>,实际的字符串“/doc/cn”、“/doc/en”都可以与之相匹配;上面的正则表达式总体由(a)(b)(c)三个带括号的部分组成:
注意: 所有编程语言,函数后变量都只能由数字字母下划线组成,并且不能以数字开头 (d)
组成部分 | 说明 |
---|---|
(a) | 匹配所有非<字符,即遇到<该部分匹配完成 |
(b) | 整体(?:)结构,表示这部分可以不出现(0/n次) (2) 匹配类型转换名称,有效的python函数名 (3) 匹配 类型转换的参数,这一部分可以不出现,有则通过()匹配始末 (4) 类型转换 后面必须跟冒号 |
© | 匹配有效的变量名(符合d) |
以上正则的匹配实例:路由会根据正则的形式,生成符合对应路径的正则表达式,用来匹配请求路径
# (1) 不匹配正则,直接路径判等
"/"
"/doc1"
# (2) (b)的类型转换不出现
"/doc2/<lang_code>"
# (3) (b)(3) 类型转换的参数不出现
"/doc3/<int:lang_code>"
# (4) 所有结构全出现
"/doc4/<string(length=2):lang_code>"