Python正则表达式re模块
1.正则表达式
正则表达式是⼀个特殊的字符序列,计算机科学的⼀个概念。通常被⽤来检索、替换那些符合某个模式(规则)的⽂本。
许多程序设计语⾔都⽀持利⽤正则表达式进⾏字符串操作。在Python中需要通过正则表达式对字符串进⾏匹配的时候,可以使⽤re模块。re 模块使 Python 语⾔拥有全部的正则表达式功能。
2.Python中的正则表达式
与⼤多数编程语⾔相同,正则表达式⾥也使⽤ \
作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配⽂本中的字符 \
,那么使⽤编程语⾔表示的正则表达式⾥将需要4个反斜杠 \
:前两个和后两个分别⽤于在编程语⾔⾥转义成反斜杠,转换成两个反斜杠后再在正则表达式⾥转义成⼀个反斜杠。
第一个参数就是正则匹配规则,第二个参数表示需要匹配的字符串。
print(re.match('\\\\', '\hello')) # 需要使⽤四个反斜杠来匹配⼀个 \
Python⾥的原⽣字符串很好地解决了这个问题,有了原⽣字符串,你再也不⽤担⼼是不是漏写了反斜杠,写出来的表达式也更直观。在Python 字符串前⾯添加 r,
即可将字符串转换成为原⽣字符串。
print(re.match(r'\\', '\hello')) # 使⽤两个反斜杠即可匹配⼀个 \
3.正则查找相关的方法
在Python中的查找匹配⽅法,常⻅的有下⾯五种,他们的⽤法⼤致相同,但是匹配出的结果却不同。
- match⽅法(只匹配字符串开头)
- search⽅法(扫描整个字符串,找到第⼀个匹配)
- findall⽅法(扫描整个字符串,找到所有的匹配)
- finditer⽅法(扫描整个字符串,找到所有的匹配,并返回⼀个可迭代对象)
- fullmatch(完整匹配,字符串需要完全满足正则规则才会有结果,否则就是None)
3.1match⽅法的使⽤
re.match尝试从字符串的起始位置匹配⼀个模式,如果不是起始位置匹配成功的话,match()就返回none。
函数语法:
re.match(pattern,string,flags=0)
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
string | 要匹配的字符串。 |
flags | 标志位,⽤于控制正则表达式的匹配⽅式,如:是否区分⼤⼩写,多⾏匹配等等。 |
我们可以使⽤group(num)函数来获取匹配表达式。
import re
result1 = re.match(r'H', 'Hello')
result2 = re.match(r'e', 'Hello')
print(result1.group(0)) # 'H' 匹配到的元素
print(result1.span()) # 匹配到的元素所在位置
print(result2) # None
3.2search⽅法的使⽤
re.search 扫描整个字符串并返回第⼀个成功的匹配。
函数语法:
re.search(pattern, string, flags=0)
示例:
import re
result1 = re.search(r'He', 'Hello')
result2 = re.search(r'lo', 'Hello')
print(result1.group(0)) # 'He' 匹配到的元素
print(result1.span()) # (0, 2)匹配到的元素所在位置
print(result2.group(0)) # 'lo'
print(result2.span()) # (3, 5)
re.match与re.search的区别
相同点:
- 1、只对字符串查询一次
- 2、返回值类型都是re.Match类型的对象
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;⽽re.search匹配整个字符串,直到找到⼀个匹配。
示例:
import re result1 = re.search(r'天⽓','今天天⽓不错哟') result2 = re.match(r'天⽓','今天天⽓不错哟') print(result1) # <re.Match object; span=(2, 4), match='天⽓'> print(result2) # None
3.3findall ⽅法的使⽤
在字符串中找到正则表达式所匹配的所有⼦串,并返回⼀个列表,如果没有找到匹配的,则返回空列表。
注意: match 和 search 是匹配⼀次 findall 匹配所有。
语法格式:
re.findall(pattern,string,flags=0)
示例代码:
import re ret = re.findall(r'\d+', 'he23ll34') print(ret) # ['23', '34'] ret = re.match(r'\d+', 'he23ll34') print(ret) # None ret = re.search(r'\d+', 'he23ll34') print(ret) # <re.Match object; span=(2, 4), match='23'>
注意事项:
findall⽅法匹配时,如果匹配规则⾥有分组,则只匹配分组数据。
import re ret = re.findall(r'\w+@(qq|126|163)\.com', '123@qq.com;aa@163.com;bb@126.com') print(ret) # ['qq', '163', '126'] 只匹配到了分组⾥的内容
如果正则表达式⾥存在多个分组,则会把多个分组匹配成元组。
import re ret = re.findall(r'\w+@(qq|126|163)(\.com)', '123@qq.com;aa@163.com;bb@126.com') print(ret) # [('qq', '.com'), ('163', '.com'), ('126', '.com')]
如果想要让findall匹配所有的内容,⽽不仅仅只是匹配正则表达式⾥的分组,可以使⽤ ?: 来将分组标记为⾮捕获分组。
import re ret = re.findall(r'\w+@(?:qq|126|163).com', '123@qq.com;aa@163.com;bb@126.com') print(ret) # ['123@qq.com', 'aa@163.com', 'bb@126.com']
3.4finditer⽅法的使⽤
和 findall 类似,在字符串中找到正则表达式所匹配的所有⼦串,并把它们作为⼀个迭代器返回。
import re ret = re.finditer(r'\d+', 'he23ll34') # 得到的结果是⼀个可迭代对象 for x in ret: # 遍历 ret 取出⾥⾯的每⼀项匹配 print(x.group(), x.span()) # 匹配对象⾥的group保存了匹配的结果
3.5fullmatch⽅法的使⽤
完整匹配,字符串需要完全满足正则规则才会有结果,否则就是None。
import re m1 = re.fullmatch(r'hello world', 'hello world') m2 = re.fullmatch(r'h.*d', 'hello world') print(m1) # <re.Match object; span=(0, 11), match='hello world'> print(m2) # <re.Match object; span=(0, 11), match='hello world'>
4.Re.Match类
4.1Re.Match类的介绍
当我们调⽤ re.match
⽅法、 re.search
⽅法,或者对 re.finditer
⽅法的结果进⾏迭代时,拿到的数据类型都是 re.Match
对象。
import re x = re.match(r'h', 'hello') y = re.search(r'e', 'hello') z = re.finditer(r'l', 'hello') print(type(x)) # <class 're.Match'> print(type(y)) # <class 're.Match'> for a in z: print(type(a)) # <class 're.Match'>
这个类⾥定义了相关的属性,可以直接让我们来使⽤。
属性和方法 |
描述 |
pos |
搜索的开始位置 |
endpos |
搜索的结束位置 |
string |
搜索的字符串 |
re |
当前使用的正则表达式对象 |
lastindex |
最后匹配的组索引 |
lastgroup |
最后匹配的组名 |
group(index) |
某个组匹配的结果 |
groups() |
所有分组的匹配结果,每个分组组成的结果以列表返回 |
groupdict() |
返回组名作为key,每个分组的匹配结果作为value的字典 |
start([group]) |
获取组的开始位置 |
end([group]) |
获取组的结束位置 |
span([group]) |
获取组的开始和结束位置 |
expand(template) |
使用组的匹配结果来替换template中的内容,并把替换后的字符串返回 |
import re ret = re.search(r'(abc)+', 'xxxabcabcabcdef') print(ret.pos) # 搜索开始的位置,默认是0 print(ret.endpos) # 搜索结束的位置,默认是字符串的⻓度 print(ret.group(0)) # abcabcabc 匹配整个表达式 print(ret.group(1)) # abc 第⼀次匹配到的结果 print(ret.span()) # (3, 12) 开始和结束位置 print(ret.groups()) # ('abc',) 表示当正则表达式⾥有多个分组时,多个分组的匹配结果
group方法表示正则表达式的分组:
- 1、在正则表达式里使用 () 表示一个分组
- 2、如果没有分组,默认只有一组
- 3、分组的下标从 0 开始
import re # 正则表达式有 4 个分组 m1 = re.search(r'(9.*)(0.*)(5.*7)', 'da9fi0rie15kfsda7ifsdaiferit') print(m1.group(0)) # 第 0 组就是把整个表达式当做一个整体 print(m1.group()) # 默认就是拿第 0 组 print(m1.group(1)) # 9fi print(m1.group(2)) # 0riel print(m1.group(3)) # 5kfsda7 print(m1.groups()) # ('9fi', '0riel', '5kfsda7') # groupdict 作用是获取到分组组成的字典 # print(m1.groupdict()) # {} # (?P<name>表达式) 可以给分组起一个名字 m2 = re.search(r'(9.*)(?P<xxx>0.*)(5.*7)', 'da9fi0rie15kfsda7ifsdaiferit') print(m2.groupdict()) # {'xxx': '0riel'} print(m2.groupdict('xxx')) # {'xxx': '0riel'} # 可以通过分组名或者分组的下标获取到分组里匹配到的字符串 print(m2.group('xxx')) # 0rie1 print(m2.group(2)) # 0rie1
4.2re.compile⽅法的使⽤
我们在使⽤正则表达式时,可以直接调⽤ re
模块的 match
,search
,findall
等⽅法,传⼊指定的正则表达式。同时,也可以调⽤re.compile
⽅法,⽣成⼀个正则表达式对象,再调⽤这个正则表达式对象的相关⽅法实现匹配。
示例:
import re re.match(r'h', 'hello') # 可以使⽤re.match⽅法直接匹配 # 也可以调⽤re模块的compile⽅法,⽣成⼀个 Pattern 对象,再调⽤ Pattern 对象的 match⽅法 regex = re.compile(r'h') print(regex.match('hello')) # <re.Match object; span=(0, 1), match='h'> re.search(r'l', 'hello') regex = re.compile(r'l') print(regex.match('hello')) # None regex = re.compile(r'l') print(regex.findall('hello')) # ['1', '1'] regex = re.compile(r'l') print(regex.finditer('hello')) # <callable_iterator object at 0x0383F930>
5.正则修饰符
5.1正则修饰符的使用
修饰符 | 描述 |
re.l | 使匹配对大小写不敏感 |
re.M | 多行匹配,影响^和$ |
re.S | 使.匹配包括换行在内的所有字符 |
示例:
import re # 正则修饰符是对正则表达式进行修饰 # . 表示除了换行以外的任意字符 # x = re.search(r'm.*a', 'sdfmo\nejoasd1') # print(x) # None # re.S:让点 . 匹配换行 x = re.search(r'm.*a', 'sdfmo\nejoasd1', re.S) print(x) # <re.Match object; span=(3, 10), match='mo\nejoa'> # re.I 忽略大小写 y = re.search(r'x', 'good Xyz', re.I) print(y) # <re.Match object; span=(5, 6), match='X'> # \w:表示的是字母数字和_ +:出现一次以上 $: 以指定的内容结尾 # re.M: 让 $ 能够匹配到换行 z = re.findall(r'\w+$', 'i am boy\n you are girl\n he is man', re.M) print(z) # ['boy', 'girl', 'man'] print(re.search(r'L', 'hello')) # None print(re.search(r'L', 'hello', re.I)) # 不区分⼤⼩写<re.Match object; span=(2, 3),match='l'> # \w+$ 表示匹配以⼀个或者多个字⺟结尾 # re.M 可以进⾏多⾏匹配,每个换⾏都认为是⼀个结尾 print(re.findall(r'\w+$', 'i am boy\n you are girl\n he is man', re.M)) # ['boy', 'girl', 'man'] # 不实⽤re.M修饰符,只会匹配到最后的 man print(re.findall(r'\w+$', 'i am boy\n you are girl\n he is man')) # ['man'] print(re.search(r'.', '\n')) # None . 匹配除了 \n 以外的所有字符 print(re.search(r'.', '\n', re.S)) # <re.Match object; span=(0, 1), match='\n'> '\n' 匹配到了 \n
5.2正则匹配规则
1.数字和字母都表示它本身,⼀个正则表达式模式中的字⺟和数字匹配同样的字符串。
re.search(r'H','Hello') # 这⾥的 H 表示的就是字⺟ H ⾃身,代表有特殊含义
2.多数字⺟和数字前加⼀个反斜杠时会拥有不同的含义。
ret = re.search(r'\d','he12ms90') # 这⾥的 \d 表示的是匹配数字
3.标点符号只有被转义时才匹配⾃身,否则它们表示特殊的含义。
ret = re.search(r'.','hello') # 这⾥的 . 表示的是匹配任意字符 ret = re.search(r'\.','he.llo') # 这⾥的 \. 进⾏了转义,才表示标点符号⾃身。
4.反斜杠本身需要使⽤反斜杠转义。由于正则表达式通常都包含反斜杠,所以你最好使⽤原始字符串来表示它们。模式元素(如 r'\t'
,等价于 \\t
)匹配相应的特殊字符。
示例:
import re # 字母x表示它本身 re.search(r'x', 'hello xyz') re.search(r'5', '23r49534') print(re.search(r'd', 'good')) # 字母d是普通的字符 print(re.search(r'\d', 'good')) # \d 有特殊含义,不再表示字母 d print(re.search(r'\d', 'wsdfk4sdfj1')) # <re.Match object; span=(5, 6), match='4'> # re.search('+','1+2') # 不能直接使用,+ 有特殊含义 print(re.search(r'\+', '1+2'))
6.正则表达式模式
下表列出了正则表达式模式语法中的特殊元素,如果你使⽤模式的同时提供了可选的标志参数,某些模式元素的含义会改变。
6.1非打印字符
⾮打印字符也可以是正则表达式的组成部分。下表列出了表示⾮打印字符的转义序列:
字符 | 含义 |
---|---|
\cx | 匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。 |
\f | 匹配一个换页符。等价于 \x0c 和 \cL。 |
\n | 匹配一个换行符。等价于 \x0a 和 \cJ。 |
\r | 匹配一个回车符。等价于 \x0d 和 \cM。 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 |
\S | 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 |
\t | 匹配一个制表符。等价于 \x09 和 \cI。 |
\v | 匹配一个垂直制表符。等价于 \x0b 和 \cK。 |
import re # \s 表示任意的空白字符 print(re.search(r'\s', 'hello world')) # 空格<re.Match object; span=(5, 6), match=' '> print(re.search(r'\n', 'hello\nworld')) # 换行<re.Match object; span=(5, 6), match='\n'> print(re.search(r'\t', 'hello\tworld')) # 制表符<re.Match object; span=(5, 6), match='\t'> # \S 表示非空白字符 print(re.search(r'\S', '\t\n x')) # <re.Match object; span=(5, 6), match='x'>
6.2特殊字符
所谓特殊字符,就是⼀些有特殊含义的字符。若要匹配这些特殊字符,必须⾸先使字符"转义",即,将反斜杠字 放在它们前⾯。下表列出了正则表达式中的特殊字符:
特殊字符 | 描述 |
() | 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用\(和\)。 |
. | 匹配除换行符 \n之外的任何单字符。要匹配 .,请使用 \.。 |
[ | 标记一个中括号表达式的开始。要匹配 [,请使用 \[。 |
\ | 将下一个字符标记为或特殊字符或原义字符、或向后引用、或八进制转义符。例如, ‘n’ 匹配字符 ‘n’。’\n’ 匹配换行符。序列 ‘\\’ 匹配 “\”,而 ‘\(’ 则匹配 “(”。 |
{ | 标记限定符表达式的开始。要匹配 {,请使用 \{。 |
| | 指明两项之间的一个选择。要匹配 |,请使用 \|。 |
\d | 匹配一个数字字符。等价于 [0-9]。 |
[0-9] | 匹配任何数字。等价于\d。 |
\D | 匹配一个非数字字符。等价于[^0-9]。 |
[a-z] | 匹配任何小写字母。 |
[A-Z] | 匹配任何大写字母 |
[a-zA-Z0-9] | 匹配任何字母即数字。等价于\w |
\w | 匹配包含下划线的任何单词字符。等价于[A-Za-z0-9_] |
\W | 匹配任何非单词字符。等价于[^A-Za-z0-9_] |
[\w4e00-\u9fa5] | 匹配纯中文 |
# 标点符号的使用:
# ():用来表示一个分组
m = re.search(r'h(\d+)x', 'sh829xkflsa')
print(m.group(1))
# 如果要表示括号,需要使用 \
m1 = re.search(r'\(.*\)', '(1+1)*3+5')
print(m1.group())
# . 表示匹配除了换行以外的任意字符。如果想要匹配 . 需要使用 \.
# [] 用来表示可选项范围 [x-y]从x到y区间,包含x和y
# m2 = re.search(r'f[a-d]m', 'pdsfcm')
# m2 = re.search(r'f[0-5]m', 'pdsf4m')
# m2 = re.search(r'f[0-5]+m', 'pdsf40m')
m2 = re.search(r'f[0-5a-dx]m', 'pdsfxm') # 0<=value<=5 或者 a<=value<=d或者value==x
print(m2)
# | 用来表示或者 和 [] 有一定的相似,但是有区别
# [] 里的值表示的是区间,而且是单个字符
# | 就是可选值,可以出现多个值
print(re.search(r'f(x|prz|t)m', 'pdsfprzm'))
# {} 用来限定前面元素出现的次数
# {n}:表示前面的元素出现 n 次
print(re.search(r'go{2}d', 'good'))
# {n,}:表示前面的元素出现 n 次以上
print(re.search(r'go{2,}d', 'gooooood'))
# {,n}:表示前面的元素出现 n 次以下
print(re.search(r'go{,2}d', 'gd'))
# {m,n}:表示前面的元素出现m到n次
print(re.search(r'go{3,5}d', 'gooood'))
import re # 字母表示它本身,很多字母前面 \ 会有特殊含义 # \n:表示换行 \t:表示一个制表符 \s:空白字符 \S:非空白字符 # \d:表示数字,等价于 [0-9] print(re.search(r'x\d+p', 'x243p')) print(re.search(r'x[0-9]+p', 'x243p')) # ^ 除了表示以指定的内容开始以外,在 [] 里还可以表示取反 # \D:表示非数字,等价于 [^0-9] print(re.search(r'\D+', 'he110')) print(re.search(r'[^0-9]+', 'he110')) # \w:表示数字、字母、 _ 以及中文等 非标点符号 print(re.findall(r'\w+', 'h+E-11.0_X*')) print(re.findall(r'\w+', '大,家+好!')) # \W: \w 取反 print(re.findall(r'\W+', 'h+E-11.0_X*'))
6.3定位符
定位符能够将正则表达式固定到⾏⾸或⾏尾。它们还能够创建这样的正则表达式,这些正则表达式出现在⼀个单词内、在⼀个单词的开头或者⼀个单词的结尾。
定位符⽤来描述字符串或单词的边界,^
和 $
分别指字符串的开始与结束,\b
描述单词的前或后边界,\B
表示⾮单词边界。
正则表达式的定位符有:
特殊字符 | 描述 |
^ | 匹配输入字符串的开始位置,例如:^h匹配以h开头;在方括号表达式中,它表示不接受该字符集合,例如[^0-9]匹配除了数字以外的数据。要匹配^字符本身,请使用^。 |
$ | 匹配输入字符串的结尾位置。要匹配$字符本身,需要使用\$。 |
\b | 匹配一个单词边界,即字与空格间的位置。 |
\B | 非单词边界匹配。 |
# ^:以指定的内容开头 $:指定内容结尾 print(re.search(r'^a.*i$', 'aofi'))
6.4限定符
限定符⽤来指定正则表达式的⼀个给定组件必须要出现多少次才能满⾜匹配。有 *
或 +
或 ?
或 {n}
或{n,}
或 {n,m}
共6种。
正则表达式的限定符有:
字符 | 描述 |
* | 匹配前面的子表达式零次或多次。例如,zo*能匹配"z"以及"zoo"。等价于{0,}。 |
+ | 匹配前面的子表达式一次或多次。例如,'zo+'能匹配"zo"以及"zoo",但不能匹配"z"。+等价于{1,}。 |
? | 匹配前面的子表达式零次或一次。例如,"do(es)"可以匹配"do"、"does"中的"does"、"doxy"中的"do"。?等价于{0,1}。 |
{n} | n是一个非负整数。匹配确定的n次。例如,'o{2}'不能匹配"Bob"中的'o',但是能匹配"food"中的两个o。 |
{n,} | n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。 |
{n,m} | m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。刘, "o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。 |
# *:表示前面的元素出现任意次数(0次及以上) 等价于 {0,} x = re.search(r'go*d', 'goooooooooooooooooooooooooooooooooooooooooooooooooooooooooood') print(x.group()) # +:表示前面的元素至少出现一次,等价于 {1,} print(re.search(r'go+d', 'goood')) # ?:两种用法: # 1.规定前面的元素最多只能出现一次,等价于 {,1} # 2.将贪婪模式转换成为非贪婪模式 print(re.search(r'go?d', 'god'))
示例:
re.search(r'\s','⼤家好 我是 代码') # 匹配所有的空字符 re.search(r'\S','⼤家') # 匹配所有的非空字符 re.search(r'\n','⼤家好\n我是代码') # 匹配换行 re.search(r'n$','hello python') # 匹配以 n 结尾 re.search(r'^h.+n$','hello python') # 匹配以 h 开头,中间出现⼀次或多次任意字符,并且以n结尾 re.search(r'^ha*','h') # 匹配以 h 开头,a出现0次或者⼀次
7.正则替换
正则表达式作用是用来对字符串进行检索和替换。
- 检索: match search fullmatch finditer findall
- 替换: sub
Python中的re模块提供了re.sub替换字符串中的匹配项。
语法:
re.sub(pattern,repl,string,count=0)
参数:
- pattern : 正则中的模式字符串。
- repl : 替换的字符串,也可为⼀个函数。
- string : 要被查找替换的原始字符串。
- count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
示例:
import re phone = "2004-959-559 # 这是⼀个电话号码" # 删除注释 num = re.sub(r'#.*$', "", phone) print("电话号码 : ", num) # # 电话号码 : 2004-959-559 # 移除非数字的内容 num = re.sub(r'\D', "", phone) print("电话号码 : ", num) # 电话号码 : 2004959559
repl可以使⽤⼀个字符串⽤来表示替换后的结果以外,还可以传⼊⼀个函数
import re def double(matched): test = int(matched.group('test')) return str(test * 2) print(re.sub(r'(?P<test>\d+)', double, 'hello23hi34')) # hello46hi68
import re t = 'afo2dlkf23af245qou3095' print(re.sub(r'\d', 'x', t)) # afoxdlkfxxafxxxqouxxxx print(re.sub(r'\d+', 'x', t)) # afoxdlkfxafxqoux p = 'hello35good50' # 把字符串里的数字 *2 # 第一个参数是正则表达式 # 第二个参数是新字符或者一个函数 # 第三个参数是需要被替换的原来的字符串 def test(x): y = int(x.group(0)) y *= 2 return str(y) # sub内部在调用 test 方法时,会把每一个匹配到的数据以re.Match的格式传参 print(re.sub(r'\d+', test, p)) # test函数是自动调用的hello70good100
8.贪婪和⾮贪婪模式
Python⾥数量词默认是贪婪的(在少数语⾔⾥也可能是默认⾮贪婪),总是尝试匹配尽可能多的字符;
⾮贪婪则相反,总是尝试匹配尽可能少的字符。
在*,?,+,{m,n}
后⾯加上?使贪婪变成⾮贪婪。
import re s = 'This is a number 234-235-22-423' r = re.match('.+(\d+-\d+-\d+-\d+)', s) print(r.group(1)) # 4-235-22-423 r = re.match('.+?(\d+-\d+-\d+-\d+)', s) print(r.group(1)) # 234-235-22-423
正则表达式模式中使⽤到通配字,那它在从左到右的顺序求值时,会尽量“抓取”满⾜匹配最⻓字符串,在我们上⾯的例⼦⾥⾯,“.+”会从字符串的启始处抓取满⾜模式的最⻓字符,其中包括我们想得到的第⼀个整型字段的中的⼤部分,“d+”只需⼀位字符就可以匹配,所以它匹配了数字“4”,⽽“.+”则匹配了从字符串起始到这个第⼀位数字4之前的所有字符。
import re print(re.match(r"aa(\d+)", "aa2343ddd").group(1)) # 2343 print(re.match(r"aa(\d+?)", "aa2343ddd").group(1)) # 2 print(re.match(r"aa(\d+)ddd", "aa2343ddd").group(1)) # 2343 print(re.match(r"aa(\d+?)ddd", "aa2343ddd").group(1)) # 2343