正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。
在 Python 中,使用 re 模块提供的函数来处理正则表达式,允许你在字符串中进行模式匹配、搜索和替换操作。
1 正则表达式
正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符"),可以用来描述和匹配字符串的特定模式。
正则表达式是一种用于模式匹配和搜索文本的工具。
正则表达式提供了一种灵活且强大的方式来查找、替换、验证和提取文本数据。
下面先给出一个简单的示例:
^
为匹配输入字符串的开始位置。[0-9]+
匹配多个数字,[0-9]
匹配单个数字,+
匹配一个或者多个。abc$
匹配字母 abc 并以 abc 结尾,$
为匹配输入字符串的结束位置。
再举一个例子,只允许用户名包含字符、数字、下划线和连接字符 -:
^
表示匹配字符串的开头。- `[a-zA-Z0-9_-]`` 表示字符集,包含小写字母、大写字母、数字、下划线和连接字符 -。
{3,15}
表示前面的字符集最少出现 3 次,最多出现 15 次,从而限制了用户名的长度在 3 到 15 个字符之间。$
表示匹配字符串的结尾。
以上的正则表达式可以匹配 runoob、runoob1、run-oob、run_oob, 但不匹配 ru,因为它包含的字母太短了,小于 3 个无法匹配。也不匹配 runoob$, 因为它包含特殊字符。
1.1 正则表达式元字符和特性
1.1.1 字符匹配
普通字符: 普通字符按照字面意义进行匹配,例如匹配字母 “a” 将匹配到文本中的 “a” 字符。
元字符: 元字符具有特殊的含义,例如 \d 匹配任意数字字符,\w 匹配任意字母数字字符,. 匹配任意字符(除了换行符)等。
1.1.2 量词
*
:匹配前面的模式零次或多次。+
:匹配前面的模式一次或多次。?
:匹配前面的模式零次或一次。{n}
:匹配前面的模式恰好 n 次。{n,}
:匹配前面的模式至少 n 次。{n,m}
:匹配前面的模式至少 n 次且不超过 m 次。
1.1.3 字符类
[ ]
:匹配括号内的任意一个字符。例如,[abc] 匹配字符 “a”、“b” 或 “c”。[^ ]
:匹配除了括号内的字符以外的任意一个字符。例如,[^abc]
匹配除了字符 “a”、“b” 或 “c” 以外的任意字符。
1.1.4 边界匹配
^
:匹配字符串的开头。$
:匹配字符串的结尾。\b
:匹配单词边界。\B
:匹配非单词边界。
1.1.5 分组和捕获
( )
:用于分组和捕获子表达式。(?: )
:用于分组但不捕获子表达式。
特殊字符\
:转义字符,用于匹配特殊字符本身。.
:匹配任意字符(除了换行符)。|
:用于指定多个模式的选择。
详细教程参考:https://www.runoob.com/regexp/regexp-tutorial.html
2 Python的正则表达式处理模块
2.1 re.match
函数
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match() 就返回 None。
函数语法:
re.match(pattern, string, flags=0)
'''
- pattern 匹配的正则表达式
- string 要匹配的字符串。
- flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志
'''
import re
print(re.match('www', 'www.runoob.com')) # 在起始位置匹配
print(re.match('com', 'www.runoob.com')) # 不在起始位置匹配
运行结果:
第一个输出的是(0,3)
,即匹配成功的索引,第二个虽然原字符串中有,但不是从起始位置开始匹配成功的,所以输出None
匹配成功 re.match 方法返回一个匹配的对象,否则返回 None。 我们可以使用 group(num)
或 groups()
匹配对象函数来获取匹配表达式。
'''
- group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
- groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
'''
import reline = "Cats are smarter than dogs"matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)
# 匹配包含 "are" 的句子,并分别捕获 "are" 前后的部分内容if matchObj:print ("matchObj.group() : ", matchObj.group())print ("matchObj.group(1) : ", matchObj.group(1))print ("matchObj.group(2) : ", matchObj.group(2))
else:print ("No match!!")
运行结果:
第一个是输出匹配的字符串,第二个是输出第一个匹配成功的元素,第三个是输出第二个匹配成功的元素,
2.2 re.search
方法
re.search 扫描整个字符串并返回第一个成功的匹配。
函数语法:
re.search(pattern, string, flags=0)
'''
- pattern 匹配的正则表达式
- string 要匹配的字符串。
- flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志
'''
import reprint(re.search('www', 'www.runoob.com')) # 在起始位置匹配
print(re.search('com', 'www.runoob.com')) # 不在起始位置匹配
运行结果:
第一个输出是’www’在字符串中的索引,第二个输出是’com’在字符串中的索引,同样可以使用group(num)
或 groups()
2.3 检索和替换
Python 的re模块提供了re.sub用于替换字符串中的匹配项。
函数语法:
前三个为必选参数,后两个为可选参数。
re.sub(pattern, repl, string, count=0, flags=0)
'''
- pattern : 正则中的模式字符串。
- repl : 替换的字符串,也可为一个函数。
- string : 要被查找替换的原始字符串。
- count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
- flags : 编译时用的匹配模式,数字形式。
'''
import rephone = "2004-959-559 # 这是一个电话号码"# 匹配以 # 开头并直到行末的所有内容,然后用空替换
num = re.sub(r'#.*$', "", phone)
print ("电话号码 : ", num)# 匹配任何非数字字符,然后用空替换
num = re.sub(r'\D', "", phone)
print ("电话号码 : ", num)
运行结果:
2.4 repl 参数
repl 参数是一个函数,以下实例中将字符串中的匹配的数字乘以 2:
import re# 将匹配的数字乘以 2
def double(matched):value = int(matched.group('value'))return str(value * 2)s = 'A23G4HFD567'
print(re.sub('(?P<value>\d+)', double, s))
# 用于匹配一个或多个数字,并将匹配的结果命名为Value,然后执行double函数
运行结果:
2.5 compile 函数
compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。
函数语法:
re.compile(pattern[, flags])
'''
- pattern : 一个字符串形式的正则表达式
- flags 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为:re.IGNORECASE 或 re.I - 使匹配对大小写不敏感re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境re.MULTILINE 或 re.M - 多行模式,改变 ^ 和 $ 的行为,使它们匹配字符串的每一行的开头和结尾。re.DOTALL 或 re.S - 使 . 匹配包括换行符在内的任意字符。re.ASCII - 使 \w, \W, \b, \B, \d, \D, \s, \S 仅匹配 ASCII 字符。re.VERBOSE 或 re.X - 忽略空格和注释,可以更清晰地组织复杂的正则表达式。这些标志可以单独使用,也可以通过按位或(|)组合使用。例如,re.IGNORECASE | re.MULTILINE 表示同时启用忽略大小写和多行模式。
'''
pattern1 = re.compile(r'\d+') # 用于匹配一个或多个连续的数字。
m1 = pattern1.match('one12twothree34four') # 从头部开始匹配
print( m1 )pattern2 = re.compile(r'\d+') # 用于匹配一个或多个连续的数字。
m2 = pattern2.search('one12twothree34four') # 都可以匹配
print( m2 )
运行结果:
2.6 findall
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果有多个匹配模式,则返回元组列表,如果没有找到匹配的,则返回空列表。
注意: match 和 search 是匹配一次 findall 匹配所有。
语法格式为:
re.findall(pattern, string, flags=0)
# 或
pattern.findall(string[, pos[, endpos]])
'''
- pattern 匹配模式。
- string 待匹配的字符串。
- pos 可选参数,指定字符串的起始位置,默认为 0。
- endpos 可选参数,指定字符串的结束位置,默认为字符串的长度。
'''
下面举一个例子,查找字符串中的所有数字:
import reresult1 = re.findall(r'\d+','runoob 123 google 456')pattern = re.compile(r'\d+') # 查找数字
result2 = pattern.findall('runoob 123 google 456')
result3 = pattern.findall('run88oob123google456', 0, 10)print(result1)
print(result2)
print(result3)
运行结果:
多个匹配模式,返回元组列表:
import re# 匹配一个或多个字母、数字或下划线组成的单词,后面紧跟着一个等号 =,再后面是一个或多个数字。这个表达式通常用来匹配类似 key=123 的键值对格式。
result = re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10')
print(result)
运行结果:
2.7 re.finditer
和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。
语法格式:
re.finditer(pattern, string, flags=0)
import reit = re.finditer(r"\d+","12a32bc43jf3")
for match in it: print (match.group() )
运行结果:
2.8 re.split
split 方法按照能够匹配的子串将字符串分割后返回列表。
语法格式:
re.split(pattern, string[, maxsplit=0, flags=0])
'''
- pattern 匹配的正则表达式
- string 要匹配的字符串。
- maxsplit 分割次数,maxsplit=1 分割一次,默认为 0,不限制次数。
- flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
'''
import re
re.split('\W+', 'runoob, runoob。runoob.')# 用于匹配一个或多个连续的非单词字符,然后以这些来分割
运行结果:
re.split('a*', 'hello world') # 对于一个找不到匹配的字符串而言,split 不会对其作出分割
运行结果:
2.9 正则表达式对象
2.9.1 re.RegexObject
re.compile() 返回 RegexObject 对象。
2.9.2 re.MatchObject
group() 返回被 RE 匹配的字符串。
start()
返回匹配开始的位置end()
返回匹配结束的位置span()
返回一个元组包含匹配 (开始,结束) 的位置
具体的正则表达式修饰符 - 可选标志、正则表达式模式、正则表达式实例这里不再详述