编程语言
首页 > 编程语言> > Python3使用re模块解析正则表达式

Python3使用re模块解析正则表达式

作者:互联网

正则表达式是编程语言中一种重要的功能,用于按指定规则从文本中匹配出指定的值。

正则表达式元字符

模式 描述
^ 匹配字符串的开头
$ 匹配字符串的末尾。
. 匹配任意字符,除了换行符,当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 次由前面的正则表达式定义的片段,贪婪方式
a b
(re) 匹配括号内的表达式,也表示一个组
(?imx) 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。
(?-imx) 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。
(?: re) 类似 (...), 但是不表示一个组
(?imx: re) 在括号中使用i, m, 或 x 可选标志
(?-imx: re) 在括号中不使用i, m, 或 x 可选标志
(?#...) 注释.
(?= re) 前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。
(?! re) 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功。
(?> re) 匹配的独立模式,省去回溯。
\w 匹配数字字母下划线
\W 匹配非数字字母下划线
\s 匹配任意空白字符,等价于 [\t\n\r\f]。
\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个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。

re.findall()

例如,有一段文本'name: Kevin age: 18 mobile: 12112345678' ,我们想提取其中的手机号。
已知,手机号码是11位的数字,我们可以用正则表达的指定格式\d{11}来描述这个规则,\d表示匹配数字,{11}表示前一项重复11次,示例如下:

import re

txt = 'name: Kevin age: 18 mobile: 12112345678' 
patten = '\d{11}'  # 匹配11个数字
print(re.findall(patten, txt))

re.findall()方法,根据匹配规则去目标文本中查找,将找到的所有符合这个格式的组合位一个列表,如果没有符合匹配的项则返回空列表。运行结果如下:

['12112345678']

re.search()

除使用re.findall()找到所有的外,我们还可以使用re.search()查找一个,示例如下:

import re

txt = 'name: Kevin age: 18 mobile: 12112345678'
patten = '\d{11}'  # 匹配11个数字

result = re.search(patten, txt)
if result is not None:  # 必须判断匹配结果不为None才能使用下面的group方法
    print(result.group())  # 使用group方法获取第一个匹配结果

运行结果如下:

12112345678

re.match()

re.search()是搜索目标字符串的部分项,我们还可以使用re.match对整个字符串形式进行匹配,示例如下:

import re

txt = 'name: Kevin age: 18 mobile: 12112345678'

# 符合目标文本完整样式的匹配规则 
patten = 'name: \w+ age: \d+ mobile: \d{11}'  

result = re.match(patten, txt)
if result is not None:  # 必须判断匹配结果不为None才能使用下面的group方法
    print(result.group())  # 使用group方法获取第一个匹配结果

其中,\w指字母或数字,+表示一个或多个前一项,即姓名匹配一个或任意多个字母或数字。
年龄 \d+则匹配一个或多个数字。
手机号码\d{}11固定匹配11位数字。运行结果如下:

name: Kevin age: 18 mobile: 12112345678

分组及命名分组

上例中如果我们相对匹配的不同信息进行提取,如我们只需要姓名Kevin、年龄18及手机号12112345678。则可以对匹配表达式中用小括号(匹配规则)进行分组,示例如下:

import re

txt = 'name: Kevin age: 18 mobile: 12112345678'

patten = 'name: (\w+) age: (\d+) mobile: (\d{11})'  # 分组匹配

result = re.match(patten, txt)
if result is not None:  # 必须判断匹配结果不为None才能使用下面的group方法
    print('姓名', result.group(1))  # 获取第1个匹配
    print('年龄', result.group(2))  # 获取第2个匹配
    print('手机号', result.group(3))  # 获取第3个匹配

运行结果如下:

姓名 Kevin
年龄 18
手机号 12112345678

当有多个匹配时,我们还可以对分组进行命名,格式为(?P<分组名>匹配规则),示例如下:

import re

txt = 'name: Kevin age: 18 mobile: 12112345678'

patten = 'name: (?P<name>\w+) age: (?P<age>\d+) mobile: (?P<mobile>\d{11})'  # 分组匹配

result = re.match(patten, txt)
if result is not None:  # 必须判断匹配结果不为None才能使用下面的group方法
    print('姓名', result.group('name'))  # 获取第1个匹配
    print('年龄', result.group('age'))  # 获取第2个匹配
    print('手机号', result.group('mobile'))  # 获取第3个匹配

运行结果同上。

re.complie()

当一个匹配规则patten经常要使用时,我们可以使用re.comple()先将该规则进行编译,然后直接使用编译后的规则进行匹配。示例如下:

import re

txt = 'name: Kevin age: 18 mobile: 12112345678'

patten = re.compile('name: (?P<name>\w+) age: (?P<age>\d+) mobile: (?P<mobile>\d{11})')  # 编译匹配规则

result = patten.match(txt)  # 使用该匹配规则进行匹配

if result is not None:  # 必须判断匹配结果不为None才能使用下面的group方法
    print('姓名', result.group('name'))  # 获取第1个匹配
    print('年龄', result.group('age'))  # 获取第2个匹配
    print('手机号', result.group('mobile'))  # 获取第3个匹配

运行结果同上。

re.sub

替换指定规则字符串,字符串的replace()方法只能对已知字符串进行替换,而re.sub则可以根据匹配规则进行替换。示例如下:

import re

txt = 'name: Kevin age: 18 mobile: 12112345678'  
patten = '\d{11}'
txt = re.sub(patten, '19122229999', txt)  # 替换里面的11位数字
print(txt)

运行结果如下:

name: Kevin age: 18 mobile: 19122229999

跨行匹配

贪婪匹配和非贪婪匹配

贪婪匹配和非贪婪匹配,当一个较长的字符串满足匹配规则和一个较短的字符串也满足相同的匹配规则时选取较长匹配还是较短匹配的问题。

import re

txt = '''name: Kevin age: 18 mobile: 12112345678 name: Lily age: 17 mobile: 19234568712'''

patten = 'name: (.*) age'  # 匹配姓名,默认贪婪匹配
print('默认贪婪匹配', re.findall(patten, txt))

patten = 'name: (.*?) age'  # 加上?表示非贪婪匹配
print('非贪婪匹配', re.findall(patten, txt))

其中.表示匹配任意字符,*表示重复任意多次,?则表示匹配0次或1次。
由于贪婪匹配会匹配最长的字符串,所以patten中的age会匹配到Lily后到age,运行结果如下:

 默认贪婪匹配 ['Kevin age: 18 mobile: 12112345678 name: Lily']
 非贪婪匹配 ['Kevin', 'Lily']
                            |

标签:匹配,name,正则表达式,age,re,result,patten,Python3
来源: https://www.cnblogs.com/superhin/p/16259645.html