Python 中的正则表达式全部用法速查
正则表达式
正则语法
特性
- 正则表达式可以拼接,如果A和B都是正则表达式,那么 AB也是正则表达式.如果字符串p匹配A并且另一个字符串q匹配B, 那么pq可以匹配 AB.这就构成了由简单构建复杂的基础.除非:
- A或者B包含低优先级操作
- A和B存在边界条件
- 存在命名组引用。
字符
元字符 : 特殊字符
它们不匹配自己,在正则中具有其它的意义,匹配自己需要转义.
元字符的完整列表:
基础字符
字符 | 功能 |
---|---|
\ | 转义 |
[ ] | 匹配一类单个字符,在里面的字符除了[- ^ \s \S \d \D \w \W] 都是普通字符 |
() | 分组.与数学中括号的作用大致相同.将括号内的内容视作一个独立字符或部分. |
零宽度断言
它们不用来代表字符,用来实现一些特殊的匹配功能
字符 | 功能 |
---|---|
| | “or”运算符,优先级非常低.存在短路现象 |
^ |
[ ]内字符集的取反,或写在模式开头,代表以模式开头.MULTILINE 模式中,可以匹配在换行符之后的字符串内的任何位置。
|
$ |
写在模式结尾,代表以模式结尾.只有\n 在结尾也算匹配成功
|
\A |
不在 MULTILINE 模式时,和 ^ 相同.MULTILINE 模式中,\A 仍然只在字符串开头匹配
|
\Z | 只匹配字符串尾 |
\b |
匹配完整单词,前后都是非字母数字字符:r'\bclass\b' .必须使用r'' ,因为Python会把\b 解析为退格
|
\B | 不在字边界时才匹配 |
\number | 匹配数字代表的组合 |
重复限定
- 它们不能直接嵌套使用,避免了非贪婪后缀
?
修饰符,和其他实现中的修饰符产生的多义性 - 可以使用括号包围再进行嵌套
字符 | 功能 |
---|---|
. | 匹配一个任意字符一次,是否包括换行符取决于DOTALL参数 |
{m,n} | 匹配前一个字符的出现次数范围, m<=出现次数<=n. 可以缺省其中一个,视为0或无上限 |
{m} | 匹配前一个字符的m个重复,少于 m 的话就会导致匹配失败 |
* | {0,} 它的匹配是 贪婪的,先尽可能多地匹配,不成功再回退. |
+ | {1,} |
? | {0,1}, 代表一个可选字符.还可做非贪婪后缀修饰符 |
一类单个字符
语法 | 含义 | 同义替换 |
---|---|---|
[abc] | a 或 b 或 c | a|b|c |
[a-z] | a-z 所有字符 | |
[^5] | 除了5所有的字符 | |
\d | 数字 | [0-9] |
\D | 非数字 | [^0-9] |
\s | 空白符 | [\t\n\r\f\v] |
\S | 非空白符 | [^ \t\n\r\f\v] |
\w | 大小写字母与数字 | [a-zA-Z0-9_ ] |
\W | 非字母与数字 | [^a-zA-Z0-9_ ] |
Python 中的正则 – re 模块
参考链接
Python re模块 官方文档
Python 正则入门 官方教程
特性
- 模式和被搜索的字符串既可以是 Unicode 字符串str ,也可以是8位字节串bytes.但不能混用.
- 反斜杠灾难: python字符串中和正则中 / 都是转义字符,所以需要二次转义.正则中一个 ‘/’ 在字符串中就会写成 ‘’.解决方法是尽量使用 Python 的原始字符串表示法,在字符串前加 r ,例如: r’/'
- 第三方模块regex, 提供了与标准库re模块兼容的API接口, 同时还提供了额外的功能和更全面的Unicode支持。
- 正则表达式模式被编译成一系列字节码,然后由用 C 编写的匹配引擎执行.
- 适当选择代码和正则: 虽然 Python 代码比精心设计的正则表达式慢,但它也可能更容易理解.
- 是Python附带的C扩展模块
API
编译正则
import re
p = re.compile('ab*')//还可以接受一个可选的flag参数,用于启用各种特殊功能和语法变体
re.compile('ab*',re.IGNORECASE)
编译标志(选项)
标志(前加 re.) | 缩写 | 含义 |
---|---|---|
ASCII | A |
使几个转义如 \w 、\b 、\s 和 \d 仅与具有相应的 ASCII 字符匹配而不是完整匹配Unicode
|
DOTALL | S |
使 . 匹配任何字符,包括换行符,否则不包括换行符
|
IGNORECASE | I | 忽略大小写 |
LOCALE | L | 进行区域设置感知匹配,应用于考虑到语言差异的程序 |
MULTILINE | M | 多行匹配,将每行(以换行符为分割)视作单独的字符串. |
VERBOSE | X | 忽略正则中不在字符类里的空格将被忽略.使用户可以使用**空格,缩进,注释(#)**美化正则的格式 |
DEBUG | 无 | 显示编译时的debug信息 |
# VERBOSE
pat = re.compile(r"""\s* # Skip leading whitespace(?P<header>[^:]+) # Header name\s* : # Whitespace, and a colon(?P<value>.*?) # The header's value -- *? used to# lose the following trailing whitespace\s*$ # Trailing whitespace to end-of-line
""", re.VERBOSE)
匹配方法
正则对象的方法和属性
方法/属性 - 正则编译后的对象.方法名() | 功能 |
---|---|
match('字符串'[,起始位置[,结束位置]])
|
从字符串开头开始匹配,返回匹配对象 |
search('字符串'[,起始位置[,结束位置]])
|
找到第一个匹配成功的子字符串,返回匹配对象 |
findall('字符串'[,起始位置[,结束位置]])
|
找到并用列表返回所有匹配的子字符串 |
finditer('字符串'[,起始位置[,结束位置]])
|
找到并返回所有匹配成功的匹配对象的iterator |
fullmatch('字符串'[,起始位置[,结束位置]])
|
对被查找串的完整匹配,相当于加了[^…$],返回匹配对象 |
split('字符串',最大分割数=0)
|
在正则匹配的所有地方将其拆分为列表.默认分割所有.就地 |
sub('表达式','字符串',替换次数=0)
|
替换匹配到的位置,默认替换所有.就地 |
subn('表达式','字符串',替换次数=0)
|
与 sub() 相同,但返回新字符串和替换次数.就地
|
flags | 标记 参数 选项 |
groups | 捕获组合的数量 |
groupindex | 命名捕获组的字典,如果没有命名捕获组则字典为空 |
pattern | 编译对象的原始样式字符串 |
模块的顶级方法
顶级函数允许同时传入正则表达式和要匹配的字符串,返回值和re.compile下方法的返回值相同
但是如果需要多次匹配,且正则表达式相同,则会进行很多次不必要的编译
每个函数还能在后面传入一个可选的标志参数,只能有一个标志
方法/属性 - re.方法名() | 功能 |
---|---|
match('表达式','字符串',标志)
|
从字符串开头开始匹配,返回匹配对象 |
search('表达式','字符串',标志)
|
找到第一个匹配成功的子字符串,返回匹配对象 |
findall('表达式','字符串',标志)
|
找到并用列表返回所有匹配的子字符串 |
finditer('表达式','字符串',标志)
|
找到并返回所有匹配成功的匹配对象的iterator |
fullmatch('表达式','字符串',标志)
|
对被查找串的完整匹配,相当于加了[^…$],返回匹配对象 |
split('表达式','字符串',切割次数=0,标志)
|
在正则匹配的所有地方将其拆分为列表.默认分割所有.就地 |
sub('表达式','替换内容','字符串',替换次数=0,标志)
|
替换匹配到的位置,默认替换所有.就地 |
subn('表达式','替换内容','字符串',替换次数=0,标志)
|
与 sub() 相同,但返回新字符串和替换次数.就地
|
escape('表达式')
|
将字符串中出现的正则元字符进行转义 |
purge()
|
清除正则表达式缓存 |
error(*msg*, *pattern=None*, *pos=None*)
|
返回一个生成的编译错误异常 |
匹配(结果)对象
可以给group()
,start()
,end()
,span()
传入参数分组的序号,以获取模式中特定分组匹配到的内容.默认参数为0.
组从0开始从左到右编号,它始终存在.要确定编号,只需计算从左到右的左括号字符.
方法/属性 - m.方法名() | 功能 |
---|---|
group(分组引用1,引用2...)
|
返回指定分组引用(数字和命名引用)匹配到的字符串,默认为引用0,即全局匹配结果 |
__getitem__(分组引用)
|
等价于m.group(g) ,允许更方便的引用一个匹配
|
groups(分组未匹配到内容的默认值=None)
|
返回一个元组,其中包含所有子组的字符串,从1开始所有子组 |
groupdict(分组未匹配到内容的默认值=None)
|
返回一个包含所有的命名子组的字典 |
start(分组引用=0)
|
返回匹配成功的开始位置,否则返回 -1 |
end(分组引用=0)
|
返回匹配成功的结束位置,否则返回 -1 |
span(分组引用=0)
|
返回元组: ( 开始位置 , 结束位置 ),未匹配到返回 ( -1,-1 ) |
expand('转义模板')
|
将结果集合中的元素,根据数字和命名引用填入到转义模板字符串的指定位置 |
pos | 正则引擎开始搜索的索引位置 |
endPos | 正则引擎结束搜索的索引位置 |
lastindex | 最后一个匹配的组的数字引用,如果没有则为None |
lastgroup | 最后一个匹配的命名组的名字,如果没有则为None |
re | 返回产生这个实例的正则对象 |
string | 返回被匹配的字符串 |
import re# 一个处理匹配结果的小例子
m=re.compile('[a-z]+').match('string goes here')
print(m.group() if m else "匹配失败") #根据结果m决定后续操作
#"string"# 一个完整的例子
pattern = re.compile(r'(\w+) (\w+) (?P<word>.*)')
match = pattern.match('I love you!')print("match.group(1,2):",match.group(1,2))
print("match[1]:",match[1])
print("match.groups():",match.groups())
print("match.groupdict():",match.groupdict())
print("match.start(2):",match.start(2))
print("match.end(2):",match.end(2))
print("match.span(2):",match.span(2))
print("match.expand(r'\\2 \\1 \\3'):",match.expand(r'\2 \1 \3'))
print("match.pos:",match.pos)
print("match.endpos:",match.endpos)
print("match.lastindex:",match.lastindex)
print("match.lastgroup:",match.lastgroup)
print("match.re:",match.re)
print("match.string:",match.string)# match.group(1,2): ('I', 'love')
# match[1]: I
# match.groups(): ('I', 'love', 'you!')
# match.groupdict(): {'word': 'you!'}
# match.start(2): 2
# match.end(2): 6
# match.span(2): (2, 6)
# match.expand(r'\2 \1 \3'): love I you!
# match.pos: 0
# match.endpos: 11
# match.lastindex: 3
# match.lastgroup: word
# match.re: re.compile('(\\w+) (\\w+) (?P<word>.*)')
# match.string: I love you!
分组扩展
基本操作
- 组从0开始编号
- 组0始终存在,表示整个正则
- 匹配对象方法以0为默认参数
- 子组从左到右从1向上编号。
- 组可以嵌套,要确定编号只需计算从左到右的左括号字符
p = re.compile('(a)b')
m = p.match('ab')
m.group() #或者 m.group(0)
#'ab'p = re.compile('(a(b)c)d')
m = p.match('abcd')m.group(0)
# 'abcd'
m.group(1)
# 'abc'
m.group(2)
# 'b'm.group(2,1,2)
# ('b', 'abc', 'b')m.groups()
# ('abc', 'b')
分组扩展的方式设置参数
(?参数)
- 参数:
'a'
,'i'
,'L'
,'m'
,'s'
,'u'
,'x'
中的一个或多个 - 标记应该在表达式字符串的首位
给patten的一部分设置参数
(?a:表达式)
(?aiLmsux-imsx:表达式)
注释
(?#注释内容)
捕获组 -> 命名组
用组名获取特定匹配结果
(?P<组名>表达式)
+ result.group('组名')
:
#匹配一个单词
p = re.compile(r'(?P<word>\b\w+\b)')
result = p.search('(((( Lots of punctuation )))')result.group('word') # 或者result.group()
#'Lots'#匹配一个时间对象
InternalDate = re.compile(r'INTERNALDATE "'r'(?P<day>[ 123][0-9])-(?P<mon>[A-Z][a-z][a-z])-'r'(?P<year>[0-9][0-9][0-9][0-9])'r' (?P<hour>[0-9][0-9]):(?P<min>[0-9][0-9]):(?P<sec>[0-9][0-9])'r' (?P<zonen>[-+])(?P<zoneh>[0-9][0-9])(?P<zonem>[0-9][0-9])'r'"')
......
m.group('zonem')
在正则后面引用前面的组
(?P<组名>表达式)
+ (?P=<组名>)
:
p = re.compile(r'\b(?P<word>\w+)\s+(?P=word)\b')
p.search('Paris in the the spring').group()
# 'the the'
传递到 re.sub()
里的 repl 参数中
非捕获组
(?:表达式)
- 对部分值进行匹配但不作为结果,也不会分配组号,当然也不能在表达式和程序中做进一步处理
- 除了无法检索组匹配内容的事实外,非捕获组的行为与捕获组完全相同
- 可以在里面放任何东西,用重复元字符重复它
- 可以用它添加新组而不更改所有其他组的编号方
import re
match = re.match(r"(?P<python>123)(?:456)(789)","123456789")
if match:print(match.group("python"))#123print(match.groups())#('123', '789')re.findall("industr(?:y|ies)","industryOpqindustries")
# ['industry', 'industries']
零宽度断言组 - 向前(右)
- 不代表字符,不会推进匹配过程
- 只用来对前面的字符进行额外的验证
- 验证通过后,还可以从断言组开始位置继续向后匹配
正面 - 类似于 if
(?=表达式)
- 类似于 if
#参考:判断一个字符串是否为[文件名.扩展名]的形式
'.*[.].*$'#判断一个字符串是否为[文件名.扩展名]的形式,且扩展名为[bat]
#在这一应用中而这效果一样,但第二种写法没必要,只是为了说明功能
#第二种写法在匹配完[bat]后又退回到了[bat]的前面重新判断[.]后的后缀格式
match = re.match(".*[.]bat$","sample.batch")
match = re.match(".*[.](?=bat$)[^.]*$","sample.batch")
负面 - 类似于 if not
(?!表达式)
#判断一个字符串是否为[文件名.扩展名]的形式,且扩展名不为[bat/exe]
match = re.match(".*[.](?!bat$|exe$)[^.]*$","sample.batch")
零宽度断言组 - 向回(左)
- 和向前断言类似
正面
(?<=表达式)
负面
(?<!表达式)
三元零宽度断言组 - 向回
(?(id/name)yes-pattern|no-pattern)
修改方法
split()
p = re.compile(r'\W+')p.split('This is a')
# ['This', 'is', 'a']p.split('This is a',1)
# ['This', 'is a']# 正则中如果有使用捕获括号,则它们的内容也将作为结果列表的一部分返回.
p = re.compile(r'\W+')
p.split('This... is a test.')
# ['This', 'is', 'a', 'test', '']p2 = re.compile(r'(\W+)')
p2.split('This... is a test.')
# ['This', '... ', 'is', ' ', 'a', ' ', 'test', '.', '']
sub()
p = re.compile('(blue|white|red)')p.sub('colour', 'blue socks and red shoes')
# 'colour socks and colour shoes'p.sub('colour', 'blue socks and red shoes', count=1)
# 'colour socks and red shoes'# 仅当空匹配(*)与前一个空匹配不相邻时,才会进行替换
p = re.compile('x*')
p.sub('-', 'abxd')
# '-a-b--d-'# replacement中的转义:
# 如果 replacement 是一个字符串,则处理其中的任何反斜杠转义。 也就是说,\n 被转换为单个换行符,\r 被转换为回车符,依此类推。 诸如 \& 之类的未知转义是孤立的
# 后向引用,例如 \6,被替换为正则中相应组匹配的子字符串。 这使你可以在生成的替换字符串中合并原始文本的部分内容
#这个例子匹配单词 section 后跟一个用 {,} 括起来的字符串,并将 section 改为 subsection
p = re.compile('section{ ( [^}]* ) }', re.VERBOSE)
p.sub(r'subsection{\1}','section{First} section{second}')
# 'subsection{First} subsection{second}'# replacement中引用由 (?P<name>...) 语法定义的命名组:
# \g<name> 将使用名为 name 的组匹配的子字符串
# \g<number> 使用相应的组号
# \g<2> 等同于 \2
# \20 将被解释为对组 20 的引用
# 以下替换都是等效的,但使用所有三种变体替换字符串:
p = re.compile('section{ (?P<name> [^}]* ) }', re.VERBOSE)
p.sub(r'subsection{\1}','section{First}')
p.sub(r'subsection{\g<1>}','section{First}')
p.sub(r'subsection{\g<name>}','section{First}')
# 'subsection{First}'# replacement 也可以是一个函数,它可以为你提供更多控制
# 如果 replacement 是一个函数,则为 pattern 的每次非重叠出现将调用该函数
# 在每次调用时,函数都会传递一个匹配的 匹配对象 参数,并可以使用此信息计算所需的替换字符串并将其返回。
# 在以下示例中,替换函数将小数转换为十六进制:
def hexrepl(match):value = int(match.group())return hex(value)p = re.compile(r'\d+')
p.sub(hexrepl, 'Call 65490 for printing, 49152 for user code.')
# 'Call 0xffd2 for printing, 0xc000 for user code.'# 使用模块级别 re.sub() 函数时,模式作为第一个参数传递。
# 图案可以作为对象或字符串提供;如果需要指定正则表达式标志,则必须使用模式对象作为第一个参数,或者在模式字符串中使用嵌入式修饰符,# sub("(?i)b+", "x", "bbbb BBBB")
# 返回 'x x'
subn()
p = re.compile('(blue|white|red)')p.subn('colour', 'blue socks and red shoes')
# ('colour socks and colour shoes', 2)p.subn('colour', 'no colours at all')
# ('no colours at all', 0)
常见问题 - 陷阱
不用正则进行简单字符串替换
如果你匹配固定字符串或单个字符类,如果你匹配固定字符串或单个字符类,并且你没有使用任何re
功能,例如IGNORECASE
标志,那么正则表达式的全部功能可能不是必需的。 字符串有几种方法可以使用固定字符串执行操作,它们通常要快得多,因为实现是一个针对此目的而优化的单个小 C 循环,而不是大型、更通用的正则表达式引擎。
- **单个子串替换,用
replace()
替换re.sub()
.**为了避免对单词的部分进行替换,模式必须是\bword\b
,以便要求word
在任何一方都有一个单词边界。这使得工作超出了replace()
的能力。 - 将多个字符替换为其它多个字符或删除,使用
translate()
替换re.sub()
在转向re
模块之前,请考虑是否可以使用更快更简单的字符串方法解决问题
区别search()
和match()
- 总体来说
search()
更强一些 - 不要偷懒在
match()
的pattern
开头加入.*
来直接代替search()
的功能.这样做会使编译器对search()
的一些优化无法发挥作用,降低来效率. - 在
search()
中,可以用'^'
作为开始来限制匹配到字符串的首位 MULTILINE
多行模式中函数match()
只匹配字符串的开始,但使用search()
和以'^'
开始的正则表达式会匹配每行的开始
贪婪与非贪婪
正则默认是贪婪模式(匹配为尽可能 少 的文字):
s = '<html><head><title>Title</title>' #32个字符
print(re.match('<.*>', s).group())
# '<html><head><title>Title</title>'
使用非贪婪的限定符
非贪婪:匹配为尽可能少的文字
*?
、 +?
、 ??
、 {m,n}?
避免用正则解析HTML
使用正则表达式解析 HTML 或 XML 很痛苦。HTML 和 XML 有特殊情况会破坏明显的正则表达式;当你编写正则表达式处理所有可能的情况时,模式将非常复杂。使用 HTML 或 XML 解析器模块来执行此类任务。
– 完 –
Python 中的正则表达式全部用法速查相关推荐
- 正则表达式在python中的应用_详解Python中的正则表达式的用法
如果直接在命令行中利用input和raw_input读入一个文件来处理,并且想要采用直接将文件拖入命令行来处理的方式, input方法可以直接处理,而如果要采用raw_input的方法的话,读入文件地 ...
- Python中Print()函数的用法___实例详解(二)(全,例多)
Python中Print()函数的用法___实例详解(二)(全,例多) 目录 十一.Print()小例子 十二.Print()中文输入显示乱码问题 十三.Print()写入文件 十四.print()在 ...
- LightGBM用法速查表
LightGBM用法速查表 1.读取csv数据并指定参数建模 # coding: utf-8 import json import lightgbm as lgb import pandas as p ...
- python的继承用法_【后端开发】python中继承有什么用法?python继承的用法详解
本篇文章给大家带来的内容是关于python中继承有什么用法?python继承的用法详解,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 面向对象三大特征 1.封装:根据职责将属性和方法 ...
- Python中re(正则表达式)模块函数学习
2019独角兽企业重金招聘Python工程师标准>>> Python正则表达式指南 今天学习了Python中有关正则表达式的知识.关于正则表达式的语法,不作过多解释,网上有许多学习的 ...
- python中index函数_详解python中的index函数用法
1.函数的创建 def fun(): #定义 print('hellow') #函数的执行代码 retrun 1 #返回值 fun() #执行函数 2.函数的参数 普通参数 :要按照顺序输入参数 de ...
- python中int函数的用法浅析_Python中int()函数的用法浅析
int()是Python的一个内部函数 Python系统帮助里面是这么说的 >>> help(int) Help on class int in module __builtin__ ...
- [Python]网络爬虫(七):Python中的正则表达式教程(转)
接下来准备用糗百做一个爬虫的小例子. 但是在这之前,先详细的整理一下Python中的正则表达式的相关内容. 正则表达式在Python爬虫中的作用就像是老师点名时用的花名册一样,是必不可少的神兵利器. ...
- [Python]网络爬虫(七):Python中的正则表达式教程
接下来准备用糗百做一个爬虫的小例子. 但是在这之前,先详细的整理一下Python中的正则表达式的相关内容. 正则表达式在Python爬虫中的作用就像是老师点名时用的花名册一样,是必不可少的神兵利器. ...
最新文章
- python文件操作举例
- css选择器(css Selectors)的语法分析
- 从移动端开发者的角度聊微软的困境和机会
- 八 python 环境安装
- 飞桨抠图直播2020.4.1
- 获取当前按钮所在行的input_form表单的input上传文件
- android 实现自动拍照,Android自定义相机实现定时拍照功能
- Maven详解及实例
- 素筛打表(输出小于n最大素数)
- 前端页面-不可编辑控制
- c语言交通灯程序闪烁,用C语言编写的交通灯程序
- 公式化学习urllib(第一卷)
- L1-019. 谁先倒-PAT团体程序设计天梯赛GPLT
- 无法登录 mysql 服务器_无法登录 MySQL服务器/无法开启 MySQL服务
- 微信小程序商城系统订单管理功能介绍
- android studio无法连接小米手机问题解决
- Java的JVM,GC是什么?
- 加拿大政府正式为IT项目管理的成本估计作出规定
- 单基因gsea_单基因如何干湿结合发5分+泛癌分析
- 关于Eureka注册中心启动报错的原因
热门文章
- 推荐 25 个优雅的 jQuery Tooltip 插件
- CD-ROM是指啥?
- whm面板降mysql_WHMCS与Cpanel/WHM面板整合方法-Cpanel/WHM管理使用教程 | 麦田一棵葱...
- 【SpringBoot整合缓存】-----spring-boot-starter-cache篇
- 我爱我专业计算机为主题的演讲稿,我爱我专业演讲稿
- java 使用7z进行解压_java调用7zip解压压缩包的实例
- 千呼万唤始出来,犹抱琵琶半遮面-go语言初识
- 一文搞懂考研数列极限问题(概念/计算/证明)史上最强/最全总结
- 计算机基础及photoshop应用试题,计算机基础及Photoshop应用选择题(计算机一级B考试卷).doc...
- 精品慕课资源推荐 计算机网络