python正则表达式
python使用正则表达式之前需要先倒入re模块
1 | import re |
可选标志位
re.A |
ASCII,使得 \w,\W,\b,\B,\s 和 \S 只匹配 ASCII 字符,而不匹配完整的 Unicode 字符。这个标志仅对 Unicode 模式有意义,并忽略字节模式。 |
re.I |
IGNORECASE,字符类和文本字符串在匹配的时候不区分大小写 |
re.L |
LOCALE,使得 \w,\W,\b 和 \B 依赖当前的语言(区域)环境,而不是 Unicode 数据库 |
re.M |
MULTILINE,通常 ^ 只匹配字符串的开头,而 $ 则匹配字符串的结尾。当这个标志被设置的时候,^ 不仅匹配字符串的开头,还匹配每一行的行首;& 不仅匹配字符串的结尾,还匹配每一行的行尾。 |
re.S |
DOTALL,使 . 匹配包括换行符在内的所有字符 |
re.X |
VERBOSE,这个标志使你的正则表达式可以写得更好看和更有条理,因为使用了这个标志,空格会被忽略(除了出现在字符类中和使用反斜杠转义的空格);这个标志同时允许你在正则表达式字符串中使用注释,# 符号后边的内容是注释,不会递交给匹配引擎(除了出现在字符类中和使用反斜杠转义的 #)。 |
可以同时使用多个标志位,方法:re.search( r'正则表达式', '字符串', re.M|re.I)
特殊字符
\d |
匹配任何十进制数字;相当于类 [0-9] |
\D |
与 \d 相反,匹配任何非十进制数字的字符;相当于类 [^0-9] |
\s |
匹配任何空白字符(包含空格、换行符、制表符等);相当于 [ \t\n\r\f\v] |
\S |
匹配任何非空白字符;相当于类 [^\t\n\r\f\v] |
\w |
匹配字母数字及下划线 |
\W |
匹配非字母数字及下划线 |
\b |
匹配单词的开始或结束 |
\B |
匹配非单词边界 |
元字符
| |
或操作符,a | b匹配a或b |
^ |
匹配字符串的开头,如果设置了 MULTILINE 标志,就会变成匹配每一行的起始位置。 |
$ |
匹配字符串的末尾。如果设置了 MULTILINE 标志,就会变成匹配每一行的结束位置。 |
. |
匹配任意单个字符,除了换行符,如果设置了DOTALL标志,则可以匹配包括换行符的任意字符。 |
[abc] |
匹配括号中的a,b,c任意单个字符,而不是abc字符串 |
[^abc] |
匹配除了a,b,c之外的任意字符 |
* |
匹配前一个字符0次或多次 |
+ |
匹配前一个字符1次或多次 |
? |
匹配前一个字符0次或1次 |
{n} |
精确匹配前一个字符 n次,例如a{3}b,可以匹配aaab |
{,n} |
匹配前一个字符0次到n次 |
{n,} |
匹配前一个字符 n次到无限次 |
{m,n} |
匹配前一个字符 m 到 n 次 |
\1...\9 |
匹配第n个分组的内容。(abc)小括号括起来的为一组\1匹配第一个小括号的组... |
1.compile函数:用于编译正则表达式,生成一个正则表达式对象
1 2 | p = re. compile (r '正则表达式' [, 可选标志位]) p.search( '待匹配内容' ).group() |
2.match函数:从字符串的起始位置开始匹配,如果起始位置匹配不成功返回none
1 | re.match(r '正则表达式' , '字符串' [,可选标志位]) |
匹配对象包含了很多方法和属性,以下几个是最重要的
group() | 返回匹配的字符串 |
start() | 返回匹配的开始位置 |
end() | 返回匹配的结束位置 |
span() | 返回一个元组表示匹配位置(开始,结束) |
3.search函数:扫描整个字符串并返回第一个成功匹配的子串
1 | re.search(r '正则表达式' , '字符串' [,可选标志位]) |
匹配对象同样包含了很多方法和属性
group() | 返回匹配的字符串 |
start() | 返回匹配的开始位置 |
end() | 返回匹配的结束位置 |
span() | 返回一个元组表示匹配位置(开始,结束) |
4.findall函数:扫描整个字符串,并返回一个列表,所有成功匹配的子串,如果没有匹配成功返回none
1 2 3 4 5 6 | r = re.findall( '\d+' , '111aaa222bbb333ccc' ) print (r) [ '111' , '222' , '333' ] #当正则表达式加上括号时,返回结果会优先显示括号内匹配到的内容 #如果不想要优先显示括号内匹配到的内容,可以在括号内顶格加上?: #(?:正则表达式) |
5.finditer函数:和findall类似,成功匹配时返回一个迭代器
1 2 3 4 | p = re. compile ( '\d+' ) iterator = p.finditer( '3只小甲鱼,15条腿,还有3条去了哪里?' ) for match in iterator: print (match.group()) |
6.sub函数:替换,类似字符串的replace
1 2 3 | >>> r = re.sub( '\d+' , 'b' , 'aaa111aaa222aaa333' ) >>> print (r) aaabaaabaaab |
7.split函数:切割
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | >>> r = re.split( '\d+' , '111aaa222bbb333ccc' ) >>> print (r) [' ', ' aaa ', ' bbb ', ' ccc'] #可以加上切割次数 >>> r = re.split( '\d+' , '111aaa222bbb333ccc' , 1 ) >>> print (r) [' ', ' aaa222bbb333ccc'] #当需要显示切割的内容时,可以在正则表达式两边加上括号 #打印时会把切割的内容一并显示 >>> r = re.split( '(\d+)' , '111aaa222bbb333ccc' ) >>> print (r) [' ', ' 111 ', ' aaa ', ' 222 ', ' bbb ', ' 333 ', ' ccc'] |
8.分组命名
1 2 3 4 5 6 7 | 定义分组:(?P<name>正则表达式) 分组引用:(?P = name) >>> r = re.search( '(?P<tag><\w+>)(?P<t>\w+)(?P=tag)' , '<h1>haha<h1>' ) >>> print (r.group( "t" )) haha >>> print (r.group( "tag" )) <h1> |
贪婪 VS 非贪婪
当重复一个正则表达式时,如果使用 a*,那么结果是尽可能多地去匹配。当你尝试匹配一对对称的定界符,例如 HTML 标志中的尖括号,默认的贪婪模式会使得你很困扰。
我们来看下例子:
1 2 3 4 5 6 7 | >>> s = '<html><head><title>Title</title>' >>> len (s) 32 >>> print (re.match( '<.*>' , s).span()) ( 0 , 32 ) >>> print (re.match( '<.*>' , s).group()) <html><head><title>Title< / title> |
RE 匹配在 <html> 的 < 后,.* 消耗掉字符串的剩余部分。由于正则表达式默认是贪婪的原因,RE 必须从字符串的尾部一个字符一个字符地回溯,直到找到匹配的 >。大家看到,按照这种方法,最后找到匹配内容竟是 <html> 的 < 开始,到</title> 的 > 结束。显然这不是你想要的结果。
在这种情况下,解决方案是使用非贪婪的限定符 *?、+?、?? 或 {m, n}?,尽可能地匹配小的文本。
1 2 | >>> print (re.match( '<.*?>' , s).group()) <html> |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能