首页 > 编程笔记 > Python笔记 阅读:33

Python re正则表达式模块的用法(非常详细)

正则表达式又称规则表达式,英文名为 Regular Expression,在代码中常简写为 regex、regexp 或 RE,是计算机科学中的一个概念。正则表达式通常用来检索、替换那些符合某个规则的文本。

正则表达式是对字符串和特殊字符操作的一种逻辑公式,用事先定义好的一些特定字符及这些特定字符的组合组成一个“规则字符串”。这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,描述在搜索文本时要匹配的一个或多个字符串。

正则表达式语法

正则表达式是一种用来匹配字符串的强有力武器。它的设计思想是一种描述性的语言给字符串定义一个规则,凡是符合规则的字符串,就认为匹配成功;否则,该字符串就是不合法的。

正则表达式并不是 Python 独有的一部分。它拥有自己独特的语法及一个独立的处理引擎。在支持正则表达式的编程语言中,正则表达式的语法都是一样的,区别只在于不同的编程语言可实现的方式不同。

字符串是编程时经常涉及的一种数据结构,需要对字符串进行操作的编程场景不胜枚举。比如,注册一个网站时,需要用户设置的密码既要有大小写字母,还要有数字和特殊字符,此时就可以使用正则表达式来匹配用户输入的密码,判断其是否满足网站对合法密码的要求。

使用正则表达式判断用户密码的设置是否合法的方法为:
在正则表达式中,如果直接给出字符,就是精确匹配。由于使用 \d 可以匹配一个数字,使用 \w 可以匹配任意大写字母、小写字母和数字,因此 \d\d\d 可以匹配 \d、\w\w\w 可以匹配 Aai,\w\d\w 可以匹配 A1a。

由于点号(.)可以匹配任意字符,因此 a. 可以匹配 aA、ai、a# 等。

以上的匹配方法均是匹配单一字符。正则表达式有多种方法匹配变长字符,如:
例如:

Python 支持常用正则表达式的语法为:

语法 说明
. 匹配任意除换行符 (\n) 之外的字符
\ 转义字符
\d 数字,0-9
\s 空白字符,如空格、\t、\n
\w 匹配所有大写字母,小写字母,数字
* 匹配前一个字符 0 次或无限次
+ 匹配前一个字符 1 次或无限次
? 匹配前一个字符 0 次或 1 次
{n} 匹配前一个字符 n 次
{n,} 匹配前一个字符至少 n 次
{n,} 匹配前一个字符 n 次到 m 次
s 匹配被匹配对象的开头

Python re模块

Python 提供了 re 模块来支持所有正则表达式的功能。

需要注意的是,由于 Python 的字符串同样使用反斜杠(\)进行转义,因此使用 r 前缀来替代。

以下两种方式均表示字符串 abc\123:
使用 re 模块的一般步骤是先将正则表达式的字符串形式编译为 Pattern 实例,再使用 Pattern 实例处理文本并获得匹配结果(一个 Match 实例),最后使用 Match 实例获得信息,进行其他的操作。

当使用 Python 的正则表达式时,re 模块的内部实际上进行了两步操作:
编译的好处就是,如果一个正则表达式需要重复使用很多次,则可以预编译该正则表达式,在重复使用时就不需要编译这个步骤了,相当于省去了第一步,直接执行第二步进行匹配,提升了效率。

re 模块的流程代码为:
import re

pattern = re.compile(r'\d+')
m = pattern.match('123Python')
if m:
    print(m.group())
else:
    print('failed')
在流程代码中,首先导入 re 模块,然后通过 re.compile() 将字符串形式的正则表达式编译为 Pattern 对象,紧接着通过 pattern.match() 去匹配字符串 '123Python',如果匹配成功,则返回匹配结果;否则,提示匹配失败。

1、match对象

在流程代码中,第 4 行的 m 是一个 match 对象,是一次匹配的结果,包含很多关于此次匹配的信息,可以使用提供的属性或方法来获取这些信息。

match 对象的属性如下:
在 Python 交互式解释器中的体验代码为:
>>> import re
>>> pattern = re.compile(r'(\d+)(\w+)(? P<loT>, *)')
>>> m = pattern.match('123Python')
>>> m.string
'123Python'
>>> m.pos
0
>>> m.endpos
9
>>> m.lastindex
3
>>> m.lastgroup
'IoT'
match 对象的方法有:
在 Python 交互式解释器中的体验代码为:
>>> import re
>>> pattern = re.compile(r'(\d+)(\w+)(? P<loT>, *)')
>>> m = pattern.match('123Python')
>>> m.group(1)
'123'
>>> m.group(2)
'Python'
>>> m.groups()
('123', 'Python', '')
>>> m.groupdict()
{'IoT':''}
>>> m.start(2)
3
>>> m.end(1)
3

2、Pattern对象

Pattern 对象是一个编译好的正则表达式,必须使用 re.compile() 进行构造,提供了多个可读属性用于获取表达式的相关信息,以及一系列方法对文本进行匹配和查找。

Pattern 对象提供的属性有:
在 Python 交互式解释器中的体验代码为:
>>> import re
>>> pattern = re.compile(r'(\d+)(\w+)(? P<loT>, *)')
>>> pattern.pattern
r'(\d+)(\w+)(? P<loT>, *)'
>>> pattern.flags
32
>>> pattern.groups
3
>>> pattern.groupindex
{'IoT': 3}
除了属性,Pattern 对象还提供了多种方法。这些方法同样可以直接被 re 使用:
1) match 在前文中已经详细介绍过了。

2) search(string[,pos[,endpos]]|re.search(pattern,string,flags))
这个方法用于查找字符串中可以匹配成功的子串,从 string 的 pos 下标处开始尝试匹配 pattern:
pos 和 endpos 的默认值分别为 0 和 len(string)。re.search() 无法指定这两个参数。参数 flags 用于编译pattern时指定匹配模式。
比如,查看字符串中是否有'Python',代码为:
import re
pattern = re.compile(r'Python')
m = pattern.search('Python-loT')
if m:
    print(m.group())
else:
    print('failed')

3) split(string[,maxsplit]|re.split(pattern,string,maxsplit)
按照能够匹配的子串将string分割后返回列表,maxsplit用于指定最大分割次数,若不指定,则全部分割。

比如,使用 split() 消除字母之间的空格,代码为:
>>> import re
>>> pattern = re.compile(r'\s+')
>>> pattern.split('a b c d')
['a', 'b', 'c', 'd']

也可以直接使用 re 调用。代码为:
>>> re.split(r'\s+', 'a b c d')
['a', 'b', 'c', 'd']

消除逗号、分号,代码为:
>>> re.split(r'[,\s]', 'a,b,c,d')
['a', 'b', 'c', 'd']

4) findall(string[,pos[,endpos]])|re.findall(pattern,string[,flags])
搜索 string,并以列表的形式返回全部能够匹配的子串。

比如,返回字符串中的所有数字,代码为:
>>> re.findall(r'\d+', 'a1b2c3d4')
['1', '2', '3', '4']

5) finditer(string[,pos[,endpos]]|re.finditer(pattern,string[,flags])
搜索 string,返回一个顺序访问每一个匹配结果的迭代器,代码为:
import re
pattern = re.compile(r'\d+')
for m in pattern.finditer('a1b2c3d4'):
    print(m.group())
运行结果为:

1
2
3
4

贪婪匹配

Python 的正则表达式默认是贪婪匹配的,也就是匹配尽可能多的字符。比如,匹配出数字 1001001000 后面的 0,代码为:
>>> re.match(r'(\d+)(0*)$', '1001000').groups()
('1001000', '')
由于 \d+ 采用贪婪匹配,把后面所有的 0 都匹配了,结果 o* 只能匹配到空字符串。因此必须让 \d+ 采用非贪婪匹配,也就是尽可能少匹配,才能把后面的 0 匹配出来,加个问号(?)就可以让 \d+ 采用非贪婪匹配,代码为:
>>> re.match(r'(\d+)(0*)$', '1001000').groups()
('1001', '000')

相关文章