python正则表达式

参考:python文档https://docs.python.org/zh-cn/3/library/re.html\#module-contents

目录

1.整体了解

  1. 语法

  2. re.match

  3. re.search 

re.match与re.search的区别

  1. 检索和替换

 repl 参数是一个函数

 6. re.compile 函数

  1. findall

  2. re.finditer

  3. re.split

  4. 正则表达式对象

re.RegexObject

re.MatchObject

  1. 正则表达式修饰符 - 可选标志

  2. 正则表达式实例


1.整体了解

正则表达式:一套规则,可以在字符串文本中进行搜查替换等
正则使用步骤:

    1. 使用 re.compile() 函数将正则表达式的字符串编译成一个 Regex对象
    1. 通过 Regex对象的一些方法,search()、match(),对文本进行匹配,匹配结果是一个 Match 对象
    1. 用 Match 对象的方法,对结果进行操作。Match对象有一个**group()**方法,它返回被查找字符串中实际匹配的文本。

正则的常用方法:

  • match:从开始位置开始查找,一次匹配,即1次匹配成功则退出
  • search:从任何位置开始查找,一次匹配
  • findall:全部匹配,返回列表
  • finditer:全部匹配,返回迭代器
  • split:分割字符串,返回列表
  • sub:替换

贪婪与非贪婪模式

  • 贪婪模式:在整个表达式匹配成功的前提下,尽可能多的匹配
  • 非贪婪模式:在整个表达式匹配成功的前提下,尽可能少的匹配

  点-星匹配所有字符:

  •      .*    ——    “贪心” 模式:它总是匹配尽可能多的文本。

  •     .*?   ——    “非贪心” 模式:匹配最短可能的字符串。

1>>> nongreedyRegex = re.compile(r'<.*?>') 2>>> mo = nongreedyRegex.search('<To serve man> for dinner.>') 3>>> mo.group() 4'<To serve man>' 5 6>>> greedyRegex = re.compile(r'<.*>') 7>>> mo = greedyRegex.search('<To serve man> for dinner.>') 8>>> mo.group() 9'<To serve man> for dinner.>' 10

python里面数量词默认是贪婪模式

例如:

查找文本abbbbbbbccc

re结果是: ab*

贪婪模式结果是:abbbbbbb

非贪婪模式结果是:a

2. 语法

模式字符串使用特殊的语法来表示一个正则表达式:

  • 字母和数字表示他们自身。一个正则表达式模式中的字母和数字匹配同样的字符串。比如 'A'、 'a'或者 '0',都是最简单的正则表达式,它们就匹配自身。你可以拼接普通字符,所以 last 匹配字符串 'last'. 
  • 多数字母和数字前加一个反斜杠时会拥有不同的含义。
  • 标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。
  • 反斜杠本身需要使用反斜杠转义。
  • 重复修饰符 (*, +, ?, {m,n}, 等) 不能直接嵌套。这样避免了非贪婪后缀 ? 修饰符,和其他实现中的修饰符产生的多义性。要应用一个内层重复嵌套,可以使用括号。 比如,表达式 (?:a{6})* 匹配6个 'a' 字符重复任意次数。

由于正则表达式通常都包含反斜杠,所以你最好使用原始字符串来表示它们。模式元素(如 r'\t',等价于 '\t')匹配相应的特殊字符。

下表列出了正则表达式模式语法中的特殊元素。如果你使用模式的同时提供了可选的标志参数,某些模式元素的含义会改变。

^ 匹配字符串的开头 $ 匹配字符串的末尾。 . 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。 只匹配一个字符 [...] 用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k' [^...] 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。 re* 匹配0个或多个的表达式。 re+ 匹配1个或多个的表达式。 re? 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式 问号在正则表达式中可能有两种含义: 声明非贪心匹配或表示可选的分组。 re{n} 精确匹配 n 个前面表达式。例如, o{2} 不能匹配 "Bob" 中的 "o",但是能匹配 "food" 中的两个 o。 re{n,} 匹配 n 个前面表达式。例如, o{2,} 不能匹配"Bob"中的"o",但能匹配 "foooood"中的所有 o。 "o{1,}" 等价于 "o+"; "o{0,}" 则等价于 "o*"。 re{n, m} 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式; re{m,n}? 前一个修饰符的非贪婪模式,只匹配尽量少的字符次数。比如,对于 'aaaaaa', a{3,5} 匹配 5个 'a' ,而 a{3,5}? 只匹配3个 'a'。 a| b 匹配a或b (re) 对正则表达式分组并记住匹配的文本 (?imx) 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。 (?-imx) 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。 (?: re) 类似 (...), 但是不表示一个组。 正则括号的非捕获版本。 匹配在括号内的任何正则表达式,但该分组所匹配的子字符串 不能 在执行匹配后被获取或是之后在模式中被引用。 (?imx: re) 在括号中使用i, m, 或 x 可选标志 (?-imx: re) 在括号中不使用i, m, 或 x 可选标志 (?#...) 注释. (?= re) 前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。比如, Isaac (?=Asimov) 匹配 'Isaac ' 只有在后面是 'Asimov' 的时候。 (?! re) 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功。比如说, Isaac (?!Asimov) 只有后面 不 是 'Asimov' 的时候才匹配 'Isaac ' 。 (?>=re) 正向后视断定,匹配的独立模式,省去回溯。如 (?<=abc)def ,并不是从 a 开始搜索,而是从 d 往回看的。你可能更加愿意使用 search() 函数,而不是 match() 函数: m = re.search('(?<=abc)def', 'gcdabcdef')     m.group(0)      #  'def' m = re.search(r'(?<=-)\w+', 'spam--egg')       m.group(0)      # 'egg'   (?<!re) 后视断定取非:类似正向后视断定,包含的样式匹配必须是定长的。 \w 匹配字母数字及下划线,等价于'[A-Za-z0-9_]'。 \W 匹配非字母数字及下划线 \s 匹配任意空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 \S 匹配任意非空字符 \d 匹配任意数字,等价于 [0-9]. \D 匹配任意非数字 \A 匹配字符串开始 \Z 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。 \z 匹配字符串结束 \G 匹配最后匹配完成的位置。 \b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。 \B 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。 \n, \t, 等. 匹配一个换行符。匹配一个制表符。等 \1...\9 匹配第n个分组的内容。 \10 匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。

(?P=name)反向引用一个命名组合;它匹配前面那个叫 name 的命名组中匹配到的串同样的字串。
(?P<name>…)(命名组合)类似正则组合,但是匹配到的子串组在外部是通过定义的 name 来获取的。组合名必须是有效的Python标识符,并且每个组合名只能用一个正则表达式定义,只能定义一次。一个符号组合同样是一个数字组合,就像这个组合没有被命名一样。

1

命名组合可以在三种上下文中引用。如果样式是 (?P<quote>['"]).*?(?P=quote) (也就是说,匹配单引号或者双引号括起来的字符串):

在正则式自身内 (?P=quote) (如示) \1 处理匹配对象 m m.group('quote') m.end('quote') (等) 传递到 re.sub() 里的 repl 参数中 \g<quote> \g<1> \1

(?(id/name)yes-pattern|no-pattern)如果给定的 id 或 name 存在,将会尝试匹配 yes-pattern ,否则就尝试匹配 no-pattern,no-pattern 可选,也可以被忽略。比如, (<)?(\w+@\w+(?:.\w+)+)(?(1)>|$) 是一个email样式匹配,将匹配 'user@host.com' 或 'user@host.com' ,但不会匹配 '<user@host.com' ,也不会匹配 'user@host.com>'。 (?(1)>|$):表示匹配的第1组若存在,将匹配>,不存在将匹配$。
\number匹配数字代表的组合。每个括号是一个组合,组合从1开始编号。比如 (.+) \1 匹配 'the the' 或者 '55 55', 但不会匹配 'thethe' (注意组合后面的空格)。这个特殊序列只能用于匹配前面99个组合。如果 number 的第一个数位是0, 或者 number 是三个八进制数,它将不会被看作是一个组合,而是八进制的数字值。在 '[' 和 ']' 字符集合内,任何数字转义都被看作是字符。
  
  

1

1m = re.search(r'(<)?(\w+@\w+(?:\.\w+)+)(?(1)>|$)','user@host.com') 2m.group(0) # 'user@host.com' 3 4m = re.search(r'(<)?(\w+@\w+(?:\.\w+)+)(?(1)>|$)','<user@host.com>') 5m.group(0) # '<user@host.com>' 6

3. re.match

re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。

函数语法:re.match(pattern, string, flags=0)

re.match()返回的是一个 <re.Match object; span=(0, 3), match='www'> 对象:

group 以str形式返回对象中match的元素 start 返回开始位置 end 返回结束位置 span 以tuple形式返回范围,包含开头,不包含结尾

当匹配成功时返回一个 Match 对象,其中:

  • group([group1, …]) 方法用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用 

group() 或  group(0);

  • start([group]) 方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0;
  • end([group]) 方法用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0;
  • span([group]) 方法返回 (start(group), end(group))。

组()的例子及区别:

                                                                                                                     

*?, +?, ??

'*', '+',和 '?' 修饰符都是 贪婪的;它们在字符串进行尽可能多的匹配。有时候并不需要这种行为。如果正则式 <.*> 希望找到 '<a> b <c>',它将会匹配整个字符串,而不仅是 '<a>'。在修饰符之后添加 ? 将使样式以 非贪婪

1`
方式或者 :dfn:
1`
最小
 方式进行匹配; 尽量  的字符将会被匹配。 使用正则式 <.*?> 将会仅仅匹配 '<a>'。

                                 

                                

解析:

首先,这是一个字符串,前面的一个 r 表示字符串为非转义的原始字符串,让编译器忽略反斜杠,也就是忽略转义字符。但是这个字符串里没有反斜杠,所以这个 r 可有可无。

  •  (.*) 第一个匹配分组,.* 代表匹配除换行符之外的所有字符。
  •  (.*?) 第二个匹配分组,.*? 后面多个问号,代表非贪婪模式,也就是说只匹配符合条件的最少字符
  •  后面的一个 .* 没有括号包围,所以不是分组,匹配效果和第一个一样,但是不计入匹配结果中。

matchObj.group() 等同于 matchObj.group(0),表示匹配到的完整文本字符

matchObj.group(1) 得到第一组匹配结果,也就是(.*)匹配到的

matchObj.group(2) 得到第二组匹配结果,也就是(.*?)匹配到的

因为只有匹配结果中只有两组,所以如果填 3 时会报错。

group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 groups() 返回一个包含所有小组字符串的元组,即多个值的元组tuple, 所以你可以使用多重复制的技巧, 每个值赋给一个独立的变量。 >>> mo.groups()                   # ('415', '555-4242') >>> areaCode, mainNumber = mo.groups() >>> print(areaCode)             # 415 >>> print(mainNumber)        # 555-4242

4. re.search 

re.search() 扫描整个字符串。

返回:一个Match对象,包含第一个成功匹配的文本。

  • 若字符串中没有找到该Regex模式,search()返回None;
  • 若找到将返回一个Match对象。Match对象有一个group()方法,它返回被查找字符串中实际匹配的文本。

函数语法:re.search(pattern, string, flags=0)

1import re 2print(re.search('www', 'www.runoob.com').span()) # 在起始位置匹配 3print(re.search('com', 'www.runoob.com').span()) # 不在起始位置匹配 4 5(0, 3) 6(11, 14) 7
1#!/usr/bin/python 2import re 3 4line = "Cats are smarter than dogs"; 5 6searchObj = re.search( r'(.*) are (.*?) .*', line, re.M|re.I) 7 8if searchObj: 9 print "searchObj.group() : ", searchObj.group() 10 print "searchObj.group(1) : ", searchObj.group(1) 11 print "searchObj.group(2) : ", searchObj.group(2) 12else: 13 print "Nothing found!!" 14 15 16searchObj.group() : Cats are smarter than dogs 17searchObj.group(1) : Cats 18searchObj.group(2) : smarter 19

re.match与re.search的区别

re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。

5. re.sub() 检索和替换

(1)Python 的 re 模块提供了re.sub用于替换字符串中的匹配项

语法:re.sub(pattern, repl, string, count=0, flags=0)    将string中检索到的pattern替换为repl

参数:

  • pattern : 正则中的模式字符串。

  • repl : 替换的字符串,也可为一个函数。

  • string : 要被查找替换的原始字符串。

  • count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。

1import re 2 3phone = "2004-959-559 # 这是一个国外电话号码" 4 5# 删除字符串中的 Python注释 6num = re.sub(r'#.*$', "", phone) # 将num中的 #.*$ 替换为空 7print("电话号码是: ", num) 8 9# 删除非数字(-)的字符串 10num = re.sub(r'\D', "", phone) 11print("电话号码是 : ", num) 12 13电话号码是: 2004-959-559 14电话号码是 : 2004959559 15

(2)Regex对象的 sub()方法:

语法:regex.sub(repl,string)

  • repl : 替换的字符串,也可为一个函数。
  • string : 要被查找替换的原始字符串。

需要传入两个参数。第一个参数是一个字符串, 用于取代发现的匹配。第二个参数是一个字符串,即正则表达式。 sub()方法返回替换完成后的字符串。例如, 在交互式环境中输入以下代码:

namesRegex = re.compile(r'Agent \w+')
namesRegex.sub('CENSORED', 'Agent Alice gave the secret documents to Agent Bob.')

'CENSORED gave the secret documents to CENSORED.

有时候,你可能需要使用匹配的文本本身,作为替换的一部分。在 sub()的第一个参数中,可以输入\1、 \2、 \3……表示“在替换中输入分组 1、 2、 3……的文本”。例如,假定想要隐去密探的姓名,只显示他们姓名的第一个字母。要做到这一点,可以使用正则表达式 Agent (\w)\w*,传入 r'\1****'作为 sub()的第一个参数。字符串中的\1 将由分组 1 匹配的文本所替代,也就是正则表达式的(\w)分组:

1import re 2 3agentRegex = re.compile(r'Agent (\w)\w*') 4agentRegex.sub(r'\1****', 'Agent Alice told Agent Carol that Agent Eve knew Agent Bob was a double agent.') 5 6结果为:A**** told C**** that E**** knew B**** was a double agent.' 7

 

repl 参数是一个函数

以下实例中将字符串中的匹配的数字乘以 2:

1import re 2 3def double(m): 4 print(m) 5 value = int(m.group('value')) 6 return str(value * 2) 7 8s = 'A23G4HFD567' 9result = re.sub('(?P<value>\d+)', double, s) 10print(result) 11 12 13<re.Match object; span=(1, 3), match='23'> 14<re.Match object; span=(4, 5), match='4'> 15<re.Match object; span=(8, 11), match='567'> 16A46G8HFD1134 17

 6. re.compile 函数

compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。

语法格式为:re.compile(pattern[, flags])

参数:

  • pattern : 一个字符串形式的正则表达式

  • flags : 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为:

关于flags更多请参考:https://docs.python.org/zh-cn/3/library/re.html\#module-contents  “模块内容” 小节

  1. re.I 忽略大小写
    1. re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
    2. re.M 多行模式
    3. re.S 即为 . 并且包括换行符在内的任意字符(. 不包括换行符)
    4. re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库
    5. re.X 为了增加可读性,忽略正则表达式字符串中的空白符和注释,这个标记允许你编写更具可读性更友好的正则表达式。通过分段和添加注释,空白符号会被忽略,如下:
1下面两个正则表达式等价地匹配一个十进制数字: 2a = re.compile(r"""\d + # the integral part 3 \. # the decimal point 4 \d * # some fractional digits""", re.X) 5b = re.compile(r"\d+\.\d*") 6 7三重引号("""), 创建了一个多行字符串。这样就可以将正则表达式定义放在多行中, 让它更可读 8

实例:

1# 1. 组只匹配字母,因此组以空格划分 2pattern = re.compile(r'([a-z]+) ([a-z]+)', re.I) 3m = pattern.match('Hello World Wide Web') 4 5print(m.group()) # Hello World 6print(m.group(1)) # Hello 7print(m.group(2)) # World 8 9 10# 2. 组匹配所有字符,包括空格,因此组是不分单词的 11pattern = re.compile(r'(.*) (.*)', re.I) # 第一组匹配除第二组匹配的,第二组默认匹配最后一个单词 12m = pattern.match('Hello World Wide Web') 13 14print(m.group()) # Hello World Wide Web 15print(m.group(1)) # Hello World Wide 16print(m.group(2)) # Web 17 18# 3. 组匹配所有字符 19pattern = re.compile(r'(.*?) (.*)', re.I) # 第一组非贪婪匹配,第二组默认匹配剩下的所有 20m = pattern.match('Hello World Wide Web') 21 22print(m.group()) # Hello World Wide Web 23print(m.group(1)) # Hello 24print(m.group(2)) # World Wide Web 25

7. findall

在字符串中找到正则表达式所匹配的所有子串。

**返回:**一个 字符串列表,包含被查找字符串中的所有匹配;如果没有找到匹配的,则返回空列表。

作为 findall()方法的返回结果的总结,请记住下面两点:

如对于findall('Cell: 415-555-9999 Work: 212-555-0000')

    1. 如果调用在一个没有分组的正则表达式上, 例如\d\d\d-\d\d\d-\d\d\d\d, 方法findall()将返回一个匹配字符串的列表, 例如['415-555-9999', '212-555-0000']。
  • 2. 如果调用在一个有分组的正则表达式上, 例如(\d\d\d)-(\d\d\d)-(\d\d\d\d), 方法 findall()将返回一个字符串的元组的列表 ( 每个分组对应一个字符串),例如[('415','555', '1122'), ('212', '555', '0000')]。

注意: match 和 search 是匹配一次, findall 匹配所有。

语法格式为:findall(string[, pos[, endpos]])

参数:

  • string : 待匹配的字符串。
  • pos : 可选参数,指定字符串的起始位置,默认为 0。
  • endpos : 可选参数,指定字符串的结束位置,默认为字符串的长度。

实例:查找字符串中的所有数字

1import re 2 3pattern = re.compile(r'\d+') # 查找数字 4result1 = pattern.findall('runoob 123 google 456') 5result2 = pattern.findall('run88oob123google456', 0, 10) 6result3 = pattern.findall('run88 oob 123google456', 0, 13) 7 8print(result1) 9print(result2) 10print(result3) 11 12['123', '456'] 13['88', '12'] 14['88', '123'] 15

re.findall(patternstringflags=0)

无法指定字符串位置

1r1 = re.findall(r'\d+','runoob 123 google 456') 2print(r1) 3 4['123', '456'] 5['123', '456'] 6 7 8r2 = re.findall(r'\d+','runoob 123 google 456', 0, 10) 9print(r2) 10 11TypeError: findall() takes from 2 to 3 positional arguments but 4 were given 12 13

8. re.finditer

和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。

语法格式为:re.finditer(pattern, string, flags=0)

1import re 2 3it = re.finditer(r"\d+","12a32bc43jf3") 4print(it) 5for match in it: 6 print(match.group()) 7 8结果: 9 <callable_iterator object at 0x000001C81079F128> 10 12 11 32 12 43 13 3 14

9. re.split

split 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:

语法格式为:re.split(pattern, string[, maxsplit=0, flags=0])

参数:

pattern 匹配的正则表达式 string 要匹配的字符串。 maxsplit 分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。 flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志

如果在 pattern 中捕获到括号,那么所有的组里的文字也会包含在列表里。如果 maxsplit 非零, 最多进行 maxsplit 次分隔, 剩下的字符全部返回到列表的最后一个元素。

\w:字母、数字、下划线。如果设置了 ASCII 标志,就只匹配 [a-zA-Z0-9_] 。

\W:匹配任何不是单词字符的字符。 这与 \w 正相反。 如果使用了 ASCII 旗标,这就等价于 [**^**a-zA-Z0-9_]。

1re.split('\W+', 'runoob, runoob, runoob.') 2['runoob', 'runoob', 'runoob', ''] 3 4re.split('(\W+)', 'runoob, runoob, runoob.') 5['runoob', ', ', 'runoob', ', ', 'runoob', '.', ''] 6 7re.split('(\W+)', ' runoob, runoob, runoob.') # 若开头、结尾有非w字符,则结果开头和结尾包含'' 8['', ' ', 'runoob', ', ', 'runoob', ', ', 'runoob', '.', ''] 9 10re.split('(\W+)', 'runoob runoob, runoob') # 若开头、结尾没有非w字符,则结果开头和结尾不包含'' 11['runoob', ' ', 'runoob', ', ', 'runoob'] 12 13re.split('(\W+)', ' runoob runoob, runoob') 14['', ' ', 'runoob', ' ', 'runoob', ', ', 'runoob'] 15

10. 正则表达式对象

re.RegexObject

re.compile() 返回 RegexObject 对象。

re.MatchObject

group() 返回被 RE 匹配的字符串。

  • start() 返回匹配开始的位置

  • end() 返回匹配结束的位置

  • span() 返回一个元组包含匹配 (开始,结束) 的位置

1pattern = re.compile(r'\d+') 2pattern # re.compile(r'\d+', re.UNICODE) 3 4m2 = pattern.match(s, 3,10) 5m2 # <re.Match object; span=(3, 5), match='12'> 6

11. 正则表达式修饰符 - 可选标志

正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:

re.I 使匹配对大小写不敏感 re.L 做本地化识别(locale-aware)匹配 re.M 多行匹配,影响 ^ 和 $ re.S 使 . 匹配包括换行在内的所有字符 re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。

12. 正则表达式实例

'(?P...)' 分组匹配

例:身份证 1102231990xxxxxxxx

1import re 2s = '1102231990xxxxxxxx' 3res = re.search('(?P<province>\d{3})(?P<city>\d{3})(?P<born_year>\d{4})',s) 4print(res.groupdict()) # 直接将匹配结果直接转为字典模式,方便使用。 5 6{'province': '110', 'city': '223', 'born_year': '1990'} 7

 

 

 

 

代码交流 2021