正则表达式(Regular expressions,也叫 REs、 regexs 或 regex patterns)
是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个" 规则字符串 ",这个"规则字符串"用来表达对字符串的一种过滤逻辑。
import re
s = 'erqwejklfkj13i903i9ioj1423847283jr' # 待匹配字符串
p = re.compile('e.{0,6}') # 创建正则对象
m = p.search(s) # 使用正则匹配待匹配字符串 获得匹配结果
函数 | 含义 | 参数 | 返回值 |
---|---|---|---|
span() | 匹配结果在原字符串中的位置 | group=0:匹配到的第n个元素组 | S:(元素起点位置,元素终点位置) F:Error |
start() | 匹配结果在原字符串中的起始位置 | group=0:匹配到的第n个元素组 | S:元素起点位置 F:Error |
end() | 匹配结果在原字符串中的终止位置 | group=0:匹配到的第n个元素组 | S:元素终点位置 F:Error |
group() | 匹配结果-字符串形式 | group=0:匹配到的第n个元素组,默认返回整个字符串匹配结果 | S:元素内容-字符串 F:Error |
groups() | 匹配结果-元组形式 | None | S:元素内容-元组 F:Error |
groupdict() | 匹配结果-字典形式 | None | S:{分组名:匹配结果} 正则分组时必须添加命名,否则返回为空字典 F:Error |
案例
a = re.search('6e\w','sfa6ef234')
print(f"匹配结果的内容为{a.group(0)},匹配结果的位置区间为{a.span()},起点位置为{a.start()},终点位置为{a.end()}")
函数 | 含义 | 参数 | 返回值 |
---|---|---|---|
match() | 确定正则是否从字符串的开头匹配 | pattern:正则 string:待匹配字符 flags:编译标志常量 | S:匹配对象 F:None |
search() | 扫描字符串,查找此正则匹配的任何位置。 | pattern:正则 string:待匹配字符 flags:编译标志常量 | S:匹配对象 F:None |
fullmatch() | 确定正则是否与整个字符串匹配 | pattern:正则 string:待匹配字符 flags:编译标志常量 | S:匹配对象 F:None |
findall() | 扫描字符串,查找此正则匹配的任何位置。 | pattern:正则 string:待匹配字符 flags:编译标志常量 | S:匹配结果字符串列表 F:None |
finditer() | 扫描字符串,查找此正则匹配的任何位置。 | pattern:正则 string:待匹配字符 flags:编译标志常量 | S:匹配对象迭代器 F:None |
案例:
# macth()
re.match('6e\w','6ef234')
# search()
re.search('6e\w','sfa6ef234')
# findall
import random
import string
r_list = string.ascii_letters + string.digits
s = ''.join([random.choice(r_list) for x in range(10000)])
p = re.compile('6e\w')
res = p.findall(s)
for a in res:
print(f"匹配结果的内容为{a}")
# finditer
import random
import string
r_list = string.ascii_letters + string.digits
s = ''.join([random.choice(r_list) for x in range(10000)])
p = re.compile('6e\w')
res = p.finditer(s)
for a in res:
print(f"匹配结果的内容为{a.group(0)},匹配结果的位置区间为{a.span()},起点位置为{a.start()},终点位置为{a.end()}")
函数 | 含义 | 参数 | 返回值 |
---|---|---|---|
sub() | 用对象替换掉字符串中用正则匹配到的对象 | pattern:替换正则 repl:替换对象 string:待匹配字符 count=0:替换次数 flags=0:编译标志常量 | S:替换后的字符串对象 F:None |
subn() | 用法同sub(),但返回值变为元组 | 用法同sub() | S:(替换后的字符串对象,替换次数) F:None |
案例
# 字符串替换字符串
re.sub(r'def\s+([a-zA-Z_][a-zA-Z_0-9]*)\s*\(\s*\):',
r'static PyObject*\npy_\1(void)\n{',
'def myfunc(): 123sdad')
# 函数替换字符串
def f(x):
print("输入参数内容为",x.group(0))
print("输入参数分组1为",x.group(1))
return '替换'
re.subn(r'def\s+([a-zA-Z_][a-zA-Z_0-9]*)\s*\(\s*\):',
f,
'def myfunc(): def myfunc():def myfunc(): def myfunc(): 123sdad')
# 限制替换次数
re.sub(r'def\s+([a-zA-Z_][a-zA-Z_0-9]*)\s*\(\s*\):',
f,
'def myfunc(): def myfunc():def myfunc(): def myfunc(): 123sdad',count=2)
函数 | 含义 | 参数 | 返回值 |
---|---|---|---|
split() | 用对象替换掉字符串中用正则匹配到的对象 | pattern:替换正则 string:待匹配字符 maxsplit=0:最大拆分次数 flags=0:编译标志常量 | S:拆分后的字符串列表 F:None |
用 pattern 分开 string 。 如果在 pattern 中捕获到括号,那么所有的组里的文字也会包含在列表里。如果 maxsplit 非零, 最多进行 maxsplit 次分隔, 剩下的字符全部返回到列表的最后一个元素。
案例:
# 普通拆分
s = 'Words, words, words.'
re.split(r'\W+', s)
# 分组拆分
s = 'Words, words, words.'
re.split(r'(\W+)', s)
# 限制拆分
s = 'Words, words, words.'
re.split(r'(\W+)', s,1)
# 如果分隔符里有捕获组合,并且匹配到字符串的开始,那么结果将会以一个空字符串开始。对于结尾也是一样
re.split(r'(\W+)', '...words, words...')
# 样式的空匹配仅在与前一个空匹配不相邻时才会拆分字符串
re.split(r'\b', 'Words, words, words.')
元字符是正则中的一种特殊字符,他门并不匹配自身,而是表示匹配一些非常规的内容,或者通过重复它们或改变它们的含义来影响正则的其他部分。
元字符 | 正则中代表的含义 |
---|---|
. | 匹配任意1个字符(除了\n) |
匹配 中列举的字符 表示连续范围时起点与终点使用"-"连接 | |
| | 匹配左右任意⼀个表达式 |
^ | 匹配字符串开头 |
$ | 匹配字符串结尾 |
匹配前⼀个字符出现0次或者⽆限次,即可有可⽆ | |
匹配前⼀个字符出现1次或者⽆限次,即⾄少有1次 | |
? | 匹配前⼀个字符出现1次或者0次,即要么有1次,要么没有 |
{ } | 匹配前⼀个字符出现多次 |
\ | 转义字符 |
( ) | 将括号中字符作为⼀个分组 |
元字符 | 正则中代表的含义 |
---|---|
^ | 匹配字符串开头 |
$ | 匹配字符串结尾 |
案例:
# 开头
a = re.search('^6','6h432h4io23h4io2')
print(a.group())
# 结尾
a = re.search('2$','6h432h4io23h4io2')
print(a.group())
元字符 | 正则中代表的含义 |
---|---|
匹配前⼀个字符出现0次或者⽆限次,即可有可⽆ | |
匹配前⼀个字符出现1次或者⽆限次,即⾄少有1次 | |
? | 匹配前⼀个字符出现1次或者0次,即要么有1次,要么没有 |
{n} | 匹配前⼀个字符出现n次 |
{n,m} | 匹配前⼀个字符出现n-m次 n省略,表示字符出现0-m次 m省略,表示字符出现n-无穷大次 |
{n,m} 不能作为正则的结尾,后必须添加其他字符,否则**.{n,m}
**的效果等同于**.{m}
**
import random
import string
r_list = string.ascii_letters + string.digits
s = ''.join([random.choice(r_list) for x in range(10000)])
# 元素可有可无
p = re.compile('e\d*L')
res = p.findall(s)
res[:5]
# 元素至少出现一次
p = re.compile('e\d+L')
res = p.findall(s)
res[:5]
# 元素最多出现一次
p = re.compile('e\d?L')
res = p.findall(s)
res[:5]
# 元素出现n次
p = re.compile('e.{3}\d')
res = p.findall(s)
res[:5]
# 元素出现n-m次
p = re.compile('e.{1,6}\d')
res = p.findall(s)
res[:5]
# 元素出现n-m次失败案例
p = re.compile('e.{1,6}')
res = p.findall(s)
res[:10]
元字符 | 正则中代表的含义 |
---|---|
. | 匹配任意1个字符(除了\n) |
匹配 中列举的字符 表示连续范围时起点与终点使用"-"连接 | |
| | 匹配左右任意⼀个表达式 |
\ | 转义字符 |
转义字符放在下面单独讲述
案例:
# 任意字符(除\n)
a = re.findall('.','\t\n\w12dfs!@%$')
print(a)
# 特定字符
a = re.findall('[1]','\t\n\w12dfs!@%$')
print(a)
a = re.findall('[1-9]','\t\n\w12dfs!@%$')
print(a)
a = re.findall('[a-z1!]','\t\n\w12dfs!@%$')
print(a)
# 多种匹配成功条件
a = re.findall('[a-z]|[0-9]','\t\n\w12dfs!@%$')
print(a)
转义字符 | 正则中代表的含义 | 等价于 |
---|---|---|
\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_ |
\A | 只匹配字符串开始 | ^ |
\Z | 只匹配字符串结束 | $ |
\b | 认可开头与结尾的空字符串 | |
\B | 任何不在开头与结尾的空字符串 | |
\1 | 引用第1个分组的内容 使用时要用r字符串取消转义 | (?p=1) |
# 数字
s = '\t\n\w12dfs!@%$'
a = re.findall('[0-9]',s)
c = re.findall('\d',s)
b = re.findall('[^0-9]',s)
d = re.findall('\D',s)
print(a,c,b,d)
# 空白字符
s = ' \t\n\f 12dfs!@%$'
a = re.findall('[ \t\n\r\f\v]',s)
c = re.findall('\s',s)
b = re.findall('[^ \t\n\r\f\v]',s)
d = re.findall('\S',s)
print(a,c,b,d)
# 数字、字母、下划线字符
s = ' \t\nDS\f -__12dfs!@%$'
a = re.findall('[a-zA-Z0-9_]',s)
c = re.findall('\w',s)
b = re.findall('[^a-zA-Z0-9_]',s)
d = re.findall('\W',s)
print(a,c,b,d)
# 位置约束-\A\Z
s = ' \t\nDS\f -__12dfs!@%$'
a = re.findall('\A[ \S]',s)
c = re.findall('^[ \S]',s)
b = re.findall('[\S]\Z',s)
d = re.findall('[\S]$',s)
print(a,c,b,d)
# 位置约束-\b \B 通常用于\w限定边界
s = ' \t\nDS\f -__12dfs!@%$'
a = re.findall('[\b\w\b]',s)
c = re.findall(' ',s)
b = re.findall('[\S]\B',s)
d = re.findall('[\S]',s)
print(a,c,b,d)
# \1 引用组 组编号可以根据实际改动
s = '7fajoi2j31227'
p = re.compile(r'^.*(.).*\1')
print(p.findall(s))
标志常量 | 正则中代表的含义 |
---|---|
re.I | 忽略大小写 |
re.M | 多行匹配模式 |
re.S | 使"."元字符也匹配换行符 |
re.U | 匹配Unicode字符(默认) |
re.A | 匹配ASCII字符 |
re.L | 根据本地设置而更改\w.\W.\b.\B.\s,以及\S的匹配内容 |
re.X | 忽略pattern中的空格,并且可以使用“#” |
# 忽略大小写
a = re.findall('a','AadfdfAjDaskhdsj',flags=re.I)
for x in a:
print(x)
# 多行匹配
s = """This line is the first,
another line,
that line, it's the best"""
a = re.findall('^[tT]h[\w\s]*',s,flags=re.M)
for x in a:
print(x)
# 匹配任意字符
s = """T
,
t"""
a = re.findall('.',s,flags=re.S)
for x in a:
print(f"匹配结果为:{x}")
# 匹配Unicode
a = re.findall('\S','结果dfAj123!@$$',flags=re.U)
for x in a:
print(f"匹配结果为:{x}")
# 匹配ASCII
a = re.findall('\w','结果dfAj123!@$$',flags=re.A)
for x in a:
print(f"匹配结果为:{x}")
在正则中添加分组,可以在结果中只选择特定内容
分组使用到的元字符:
元字符 | 正则中代表的含义 |
---|---|
( ) | 将括号中字符作为⼀个分组 |
分组的查看方法见前文中 匹配结果查看方法
分组语法 | 含义 |
---|---|
(?P\<a>.....) | 将该分组命名为a,同一个正则中每个组的命名唯一 |
(?P=a) | 引用在此之前的名为a的组中的值 多用于匹配引号内的内容 |
(?Lmsux) | 设置匹配标志,可以是左边字符以及它们的组合 其含义与匹配时添加编译标志常量相同 |
(?#…) | 表示注释 |
(?:…) | 匹配但不捕获该匹配的子表达式 |
(?=…) | 用于正则表达式之后,表示如果"=“后的内容在字符串中出现则匹配,但不返回”="后的内容 |
(?!..) | 用于正则表达式之后,表示如果"!“后的内容未在字符串中出现则匹配,但不返回”!"后的内容 |
(?<=…) | 用于正则表达式之前,与(?=…)含义相同 |
(?<!..) | 用于正则表达式之前,与(?!..)含义相同 |
(?(id/name)yes-pattern|no-pattern) | 先匹配 id 或者 name 对应的分组,如果能匹配到,就继续匹配 yes-pattern;如果不能匹配到,就继续匹配 no-pattern |
案例:
# 分组命名
p = re.compile('(?P<a>e.{1,6}d).{1,10}(?P<b>[\w]{1,3})')
print(p.search(s).group('a'),p.search(s).groupdict())
# 命名引用
s = ''.join([random.choice(r_list) for x in range(10000)])
p = re.compile('(?P<a>[\'"]).{1,10}(?P=a)')
print(p.search(s).group(),p.search(s).groupdict())
# 添加匹配标志
result = re.findall(r'(?im)(^th[\w\s]+) (l[\w]*)', '''
This Line Is The First,
another line,
that line, it's the best
''')
print(result)
# 匹配但不捕获-?:
result = re.findall(r'(?im)(^th[\w\s]+)(?:l[\w]*)', '''
This Line Is The First,
another line,
that line, it's the best
''')
print(result)
# 匹配但不捕获(从后方)-?=
result = re.findall(r'(?im)(^th[\w\s]+)(?=l[\w]*)', '''
This Line Is The First,
another line,
that line, it's the best
''')
print(result)
# 匹配但不捕获(从前方)-?<=
result = re.findall(r'(?im)(?<=[ ,])(i[\w\s]+)', '''
This Line Is The First,
another line,
that line, it's the best
''')
print(result)
# 不匹配但不捕获(从后方)-?!
result = re.findall(r'(?im)(^th[\w\s]+)(?![h-z,])', '''
This Line Is The First,
another line,
that line, it's the best
''')
print(result)
# 不匹配但不捕获(从前方)-?<!
result = re.findall(r'(?im)(?<![ ,])(i[\w\s]+)', '''
This Line Is The First,
another line,
that line, it's the best
''')
print(result)
# 注释
result = re.findall(r'(?im)(^th[\w\s]+) (?#注释)', '''
This Line Is The First,
another line,
that line, it's the best
''')
print(result)
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。