Python正则表达式实战指南
一 正则表达式库
正则表达式是文本处理中不可或缺的强大工具,Python通过re
模块提供了完整的正则表达式支持。本文将详细介绍re
模块中最常用的match()
、search()
和findall()
函数,以及贪婪模式与非贪婪模式的区别,帮助读者掌握Python中正则表达式的核心用法。
1. re.match()函数:从字符串开头匹配
re.match()
是正则表达式最基本的函数之一,它尝试从字符串的起始位置匹配一个模式。
基本语法与参数
re.match(pattern, string, flags=0)
- pattern:要匹配的正则表达式字符串或预编译的正则对象
- string:要匹配的目标字符串
- flags:可选标志,用于控制正则表达式的匹配方式
返回值特性
- 匹配成功时返回
Match
对象 - 匹配失败时返回
None
典型使用示例
import rea='1,2,3,4,5'result1=re.match('1,',a)#必须以这个参数开头才行
result2=re.match('2',a)print(result1) #返回match对象
print(result2) #结果为空
<re.Match object; span=(0, 2), match='1,'>
其中span参数代表匹配成功 的起始和末尾的位置。match代表匹配的值为什么
2. re.search()函数:扫描整个字符串
与match()
不同,re.search()
会扫描整个字符串查找第一个匹配项,不限于字符串开头。
基本语法
re.search(pattern, string, flags=0)
参数与match()
相同,但行为不同。
import re
a='1,2,3,4,5,3'
result=re.search('3',a) #可以不以这个参数开头,但只返回第一个匹配的信息
print(result)
<re.Match object; span=(4, 5), match='3'>
根据输出结果我们可以看出,search()只返回了第一个查到的值的信息。
与match()的关键区别
特性 | re.match() | re.search() |
---|---|---|
匹配位置 | 仅字符串开头 | 字符串任意位置 |
使用频率 | 较少 | 较多 |
性能 | 稍快 | 稍慢 |
典型用途 | 验证开头格式 | 查找内容 |
3. re.findall()函数:查找所有匹配项
re.findall()
返回字符串中所有与模式匹配的非重叠匹配项列表。
基本语法
re.findall(pattern, string, flags=0)
返回值特点
- 返回包含所有匹配子串的列表
- 没有匹配时返回空列表
- 如果正则中有分组,则返回分组元组列表
import re
a='as1m,23f,asd3,23f,112'
res1=re.findall('2',a)
print(res1)
['2', '2', '2']
可以看出,这个把匹配的所有结果都返回了,但我们也会发现,这个返回的是一个列表形式,很利于处理。
与match/search的区别
match
:只在开头查找单个匹配search
:在整个字符串查找单个匹配findall
:查找所有非重叠匹配
前面只是开胃小菜,下面请看他们结合正则表达式所展现的绚丽操作吧
4 表示字符范围
先举例子再说概念
import re
massage='pig98dog80'
res1=re.findall('[io]',massage)
res2=re.findall('[a-z]',massage)
res3=re.findall('[0-9]',massage)
print(res1)
print(res2)
print(res3)
输出
['i', 'o']
['p', 'i', 'g', 'd', 'o', 'g']
['9', '8', '8', '0']
根据上面实例我们可以看出
[io]所表示的是在这个字符串中,出现i或o都会被提取出来,类比,我们也可以想到[90]表示的不是90,而是表示这个‘9’和‘0’两个字符
[a-z]所表示的是在这个字符串中,出现在a-z范围中的都会被提取出来
[0-9]所表示的是在这个字符串中,出现在0-9范围中的都会被提取出来
5 表示字符出现的次数
还是先举例子再说概念
import remassage='abcdacdabb'
res=re.findall('ab*',massage)
print('ab*型:',res)res1=re.findall('ab+',massage)
print('ab+型:',res1)res2=re.findall('ab?',massage)
print('ab?型:',res2)
结果
ab*型: ['ab', 'a', 'abb']
ab+型: ['ab', 'abb']
ab?型: ['ab', 'a', 'ab']
根据这个结果,在格式上我们可以看出区别,b后面跟的分别是*+?,然后结果也很明显,第一种b分别出现了0,1,2次,第二种b分别出线了1,2次,第三种情况出现了1,0,1次
我们我们可以知道
ab*这种类型,可以提取*前面的数据(字母,数字,或者符号)出现任意次数的情况
ab+这种类型,可以提取*前面的数据(字母,数字,或者符号)最少出现一次的类型
ab*这种类型,可以提取*前面的数据(字母,数字,或者符号)出现0-1次的类型
import re
message='0123456'
mes=re.findall('^0',message)
mes1=re.findall('^6',message)
mes2=re.findall('0$',message)
mes3=re.findall('6$',message)
print('^0型',mes)
print('^6型',mes1)
print('0$型',mes2)
print('6$型',mes3)
输出
^0型 ['0']
^6型 []
0$型 []
6$型 ['6']
我们可以看出在对于同一串字符串,当0在行首时^0就可以识别出来有结果,^6就返回空值,同理$也是
所以
^所选这的是这个字符后面在行首的情况
$所选这的是这个字符前面在行尾的情况
res=re.findall('f[o]{3}',a)
res1=re.findall('f[o]{3,}',a)
res2=re.findall('f[o]{3,6}',a)
print(res)
print(res1)
print(res2)
结果
['fooo']
['foooooooooooo']
['foooooo']
这个我们可以看出[o]{3}就对于ooo,[o]{3,}结果就是取了全部的o,[o]{3,6}取了最大6个o
总结
ab*这种类型,可以提取*前面的数据(字母,数字,或者符号)出现任意次数的情况
ab+这种类型,可以提取*前面的数据(字母,数字,或者符号)最少出现一次的类型
ab*这种类型,可以提取*前面的数据(字母,数字,或者符号)出现0-1次的类型
^所选这的是这个字符后面在行首的情况
$所选这的是这个字符前面在行尾的情况
[o]{3} 表示3个
[o]{3,} 表示3个以上
{o]{3,6} 表示3-6个但一般没有参数控制会是6个
6 表示同一类字符
正则表达式元字符详解
以下是对常用正则表达式元字符的解释和用法说明:
\d
匹配任意数字字符,等价于 [0-9]
。例如匹配电话号码中的数字部分。
\D
匹配任意非数字字符,等价于 [^0-9]
。例如匹配非数字分隔符。
\s
匹配任意空白字符,包括空格、制表符、换行符等。例如匹配文本中的空格分隔符。
\S
匹配任意非空白字符。例如匹配连续的非空白文本。
\w
匹配任意单词字符,包括字母、数字和下划线,等价于 [A-Za-z0-9_]
。例如匹配变量名。
\W
匹配任意非单词字符。例如匹配特殊符号。
\b
匹配单词边界。例如精确匹配整个单词 "the" 可以写作 \bthe\b
。
\B
匹配非单词边界。例如匹配 "the" 但排除 "there" 中的 "the"。
\f
匹配换页符(Form feed)。
\n
匹配换行符(Line feed)。
\r
匹配回车符(Carriage return)。
\v
匹配垂直制表符(Vertical tab)。
.
匹配除换行符外的任意单个字符。例如匹配 "a.c" 可以匹配 "abc"、"aXc" 等。
使用示例
// 匹配所有数字
a = "123abc".match(/\d/g); // ["1", "2", "3"]// 匹配非数字
b = "123abc".match(/\D/g); // ["a", "b", "c"]// 匹配空白字符
c = "a b\tc".match(/\s/g); // [" ", "\t"]// 匹配单词边界
d = "hello world".match(/\b\w+\b/g); // ["hello", "world"]
这些元字符可以组合使用构建更复杂的正则表达式模式,满足各种文本匹配需求。
6. 贪婪模式与非贪婪模式
正则表达式中的量词(如*
, +
, ?
, {}
)默认采用贪婪匹配,会尽可能多地匹配字符。通过在量词后添加?
可启用非贪婪匹配,尽可能少地匹配字符。
贪婪匹配示例
text = "Here is <div>sometext</div> with <div>tags</div>."
pattern = r'<.*>'
match = re.search(pattern, text)
print(match.group()) # 输出: <div>sometext</div> with <div>tags</div>
非贪婪匹配示例
pattern = r'<.*?>'
matches = re.findall(pattern, text)
print(matches) # 输出: ['<div>', '</div>', '<div>', '</div>']
关键区别总结
模式 | 表示方法 | 匹配行为 | 适用场景 |
---|---|---|---|
贪婪 | * , + , ? , {} | 尽可能多匹配 | 提取最大可能内容 |
非贪婪 | *? , +? , ?? , {}? | 尽可能少匹配 | 提取最小单位内容 |
综合应用建议
- 性能考虑:对于频繁使用的正则表达式,使用
re.compile()
预编译可提高效率 - 错误处理:总是检查匹配结果是否为None再调用group()
- 模式选择:
- 验证字符串格式→
match
- 查找内容→
search
- 提取所有匹配→
findall
- 验证字符串格式→
- 贪婪控制:处理HTML/XML等嵌套结构时,非贪婪模式通常更安全
通过掌握这些核心函数和模式,您将能够高效处理大多数文本匹配和提取任务。正则表达式虽然复杂,但一旦掌握将成为您文本处理的强大武器。
7 或和组
或用|表示
组用(表达式)
5实战
读取html中的内容
import re
f1=open(r'D:\培训\中国城市名称大全.html','r',encoding='utf-8')
f2=open('城市大全.csv1','w')
ls=[]
for line in f1:# <div class="para" label-module="para">郑州市 洛阳市 焦作市 商丘市 信阳市 周口市 鹤壁市 安阳市 濮阳市 驻马店市</div>res=re.findall('<div class="para" label-module="para">(.+)</div>', line)if len(res)>0:ls = ls+res# print(re.findall("para>(.+)<", line))
for i in ls:f2.write(str(i)+',')# print(i)
f1.close()
f2.close()
二 第三方库
第三方库,我们用一般用 pip在cmd终端安装,也可以在pycharm终端安装。
主要通过
我们还可以在后面加
-i https://pypi.tuna.tsinghua.edu.cn/simple
来使用清华源的镜像源来安装