正则表达式(二)
转义字符
- 在 Python 的正则表达式中,转义字符用来表示那些在字符串中有特殊意义的字符。如果你想要匹配这些字符本身,而不是它们在正则表达式中的特殊功能,你需要在它们前面加上反斜杠(
\
)来进行转义。 - 当你使用 Python 字符串时,也可能需要对反斜杠进行转义。例如,为了匹配一个字面上的反斜杠,你可能需要在正则表达式字符串中写两个反斜杠
\\
来对其进行转义。因为在Python字符串中,一个反斜杠已经用来转义了。所以,要匹配一个反斜杠,正则表达式字符串通常是'\\\\'
。但是,如果你使用了Python的原始字符串(在字符串前加上r
或R
),就不需要这么做了,比如r'\\'
。
贪婪匹配
- **贪婪:**最大限度的匹配,正则的匹配的默认是贪婪的。
- **非贪婪:**只要满足匹配条件,能少匹配就少匹配,通常使用 ? 取消贪婪
- 示例:
1
2
3
4
5
6
7
8
9
10import re
# c = re.compile(r'a.*?c')
c = re.compile(r'a.+?c')
s = c.search('abcasdhadfhadc')
if s:
print('ok')
print(s.group())
分组匹配
- ():可以表示一个整体,也可以用来分组匹配。
group([group1, ...])
:返回一个或者多个匹配的子组。如果只有一个参数,结果就是一个字符串,如果有多个参数,结果就是一个元组。groups(default=None)
:返回一个元组,包含所有匹配的子组,在样式中出现的从1到任意多的组合。 default 参数用于不参与匹配的情况,默认为None
。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import re
c = re.compile(r'(\d+)([a-z]+)(\d+)')
s = c.search('abca123sdha456dfhadc')
if s:
print('ok')
print(s.group()) # 123sdha456
# 等价于上式
print(s.group(0)) # 123sdha456
# 里面的数字表示第几个分组,也就是第几个小括号匹配的结果
print(s.group(1)) # 123
print(s.group(2)) # sdha
print(s.group(3)) # 456
print(s.group(1, 2, 3)) # ('123', 'sdha', '456')
print(s.groups()) # ('123', 'sdha', '456')groupdict(default=None)
:返回一个字典,包含了所有的 命名 子组。key就是组名。 default 参数用于不参与匹配的组合,默认为None
。- lastindex:捕获组的最后一个匹配的整数索引值,如果没有匹配产生的话则为
None
。 - lastgroup:最后一个匹配的命名组名字,如果没有产生匹配的话则为
None
。1
2
3
4
5
6
7
8
9
10import re
s = '4107821995xxxxxxxx'
res = re.search('(?P<province>\d{3})(?P<city>\d{3})(?P<born_year>\d{4})', s)
print(res.groupdict())
# {'province': '410', 'city': '782', 'born_year': '1995'}
print(res.lastindex)
# 3
print(res.lastgroup)
# born_year \number
:匹配数字代表的组合。每个括号是一个组合,组合从1开始编号。(?P<name>…)
:命名组合,类似正则组合,但是匹配到的子串组在外部是通过定义的 name 来获取的。(?P=name)
:反向引用一个命名组合,它匹配前面那个叫 name 的命名组中匹配到的串同样的字串。1
2
3
4
5
6
7
8
9
10
11
12
13import re
# 正则中的\1:表示前面第一个小括号匹配的结果
# c = re.compile(r'<([a-z]+)><([a-z]+)>\w*</\2></\1>')
# c = re.compile(r'<(?P<hello>[a-z]+)><(?P<world>[a-z]+)>\w*</\2></\1>')
# 可以给指定的分组起个名字
c = re.compile(r'<(?P<hello>[a-z]+)><(?P<world>[a-z]+)>\w*</(?P=world)></(?P=hello)>')
s = c.search('xxx<div><a>百度一下</a></div>yyy')
if s:
print('ok')
print(s.group())
匹配模式
- **说明:**可以对匹配的模式作出整体的修饰处理,如:忽略大小写等
修饰符 描述 re.I 使匹配对大小写不敏感,即:忽略大小写 re.L 做本地化识别(locale-aware)匹配 re.M 多行匹配,影响 ^ 和 $ re.S 单行匹配,或使 '.'
匹配包括换行('\n'
)在内的所有字符re.U 根据Unicode字符集解析字符。这个标志影响 \w、\W、\b、\B re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解 - 示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23import re
# 忽略大小写
# c = re.compile(r'hello', re.I)
# 多行匹配
# c = re.compile(r'^hello', re.M)
# 作为单行处理,或让 '.' 匹配 '\n'
c = re.compile(r'<div>.*?</div>', re.S)
# string = '<div>hello</div>'
string = '''<div>
hello
</div>
'''
s = c.search(string)
if s:
print('ok')
print(s.group())
字符串切割
- **说明:**某些情况下,无法通过字符串函数进行切割,可以使用正则的方式处理,如:按照数字切割
1
re.split(pattern, string[, maxsplit=0, flags=0])
- 参数:
- pattern:匹配的正则表达式。
- string:要匹配的字符串。
- maxsplit:分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。
- 示例:
1
2
3
4
5
6
7
8
9
10
11import re
c = re.compile(r'\d')
string = '正则1其实不难2但是学完发现自己写不出来3是这样吧'
# 按照正则进行切割,maxsplit可以指定切割次数,默认不限制,等价于:re.split()
ret = c.split(string, maxsplit=1)
print(ret)
print(type(ret))
字符串的替换
- **说明:**简单的替换可以自己处理,要按照正则规律进行替换就需要使用专门的函数
1
re.sub(pattern, repl, string, count=0, flags=0)
- 参数:
- pattern:匹配的正则表达式。
- repl:替换的字符串,也可为一个函数。
- string:要被查找替换的原始字符串。
- count:模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
- 示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24import re
'''
# 简单的正则替换,不需要人为干预替换过程
c = re.compile(r'\d')
string = 'jgaabcak1dadjf2abcfal1ks3jdfabc'
ret = c.sub('yyy', string)
print(ret)
'''
def deal(s):
# 参数是每一个匹配整个的正则结果的对象
ret = int(s.group())
# 会使用该函数返回的字符串替换对应的匹配
return str(ret * 2)
# 可以干预正则替换的过程,传递一个函数
ret = re.sub(r'\d', deal, 'dasf1af2af3af4afd')
print(ret)