欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > Python 正则表达式全攻略:从入门到精通实战教程

Python 正则表达式全攻略:从入门到精通实战教程

2025/2/22 17:01:46 来源:https://blog.csdn.net/tekin_cn/article/details/145720647  浏览:    关键词:Python 正则表达式全攻略:从入门到精通实战教程

正则表达式在文本处理领域占据着举足轻重的地位,它能够帮助开发者高效地进行复杂字符串的匹配、提取和替换操作。本教程聚焦于 Python 中的正则表达式,以re模块为核心,从基础概念到高级应用,全方位深入剖析其使用技巧。无论是编程新手还是经验丰富的开发者,都能通过丰富的示例代码、清晰的图文及表格对比,获取实用知识,大幅提升文本处理能力。

正则表达式基础概念

  • 定义与用途:正则表达式是嵌入 Python 并通过re模块提供的一种小型、高度专业化的编程语言,用于定义字符串匹配规则。它可用于匹配英文句子、邮箱地址等各类字符串,还能进行字符串修改和拆分。

  • 匹配字符

    • 普通字符匹配:大多数字母和符号会直接匹配自身,如test就匹配test

    • 元字符匹配:像[]\等元字符有特殊含义。[]用于指定字符类,如[abc]匹配abc中任意一个字符,等同于[a - c]^在字符类开头表示取反,如[^5]匹配除5以外的字符 。反斜杠\用于表示特殊序列或转义元字符,如\w匹配字母数字字符,在bytes类型中相当于[a-zA-Z0-9_] ,在str类型中根据unicodedata模块匹配 Unicode 数据库中的字母字符。常见特殊序列包括\d(匹配数字,等价于[0-9])、\D(匹配非数字字符,等价于[^0-9])、\s(匹配空白字符,等价于[\t\n\r\f\v])、\S(匹配非空白字符,等价于[^\t\n\r\f\v])、\w(匹配字母数字字符,等价于[a-zA-Z0-9_])、\W(匹配非字母数字字符,等价于[a-zA-Z0-9_] )。[.匹配除换行符外的任何字符,在re.DOTALL模式下可匹配换行符。

元字符详解

  • 字符类相关元字符[]用于创建字符类,定义匹配的字符集合。例如在一个处理文本数据的项目中,需要提取所有的元音字母,就可以使用[aeiou]这个正则表达式。假设文本内容为"hello world",使用re.findall('[aeiou]', "hello world"),就能得到['e', 'o', 'o']。在字符类中,元字符(除\外)失去特殊含义,如[akm$]匹配akm$^在字符类开头表示取反,在验证用户输入的密码强度时,要求密码不能包含特殊字符(这里假设特殊字符为除字母、数字和下划线之外的字符),可以用re.search('[^a-zA-Z0-9_]', password)来检查,如果匹配到内容,说明密码包含特殊字符,不符合要求。

  • 重复相关元字符*表示前一个字符可匹配零次或更多次,在解析数学表达式时,比如解析形如x^nn为整数)的幂运算表达式,x\^[0-9]*就可以匹配x^后面跟着任意个数字的情况,像x^2x^100等都能匹配。+表示匹配一次或更多次,在验证手机号码格式时,国内手机号码第一位是1,第二位可以是3456789,后面跟着 9 位数字,1[3-9]\d{9}就能准确匹配手机号码,这里\d{9}表示匹配 9 个数字,+类似,但+要求至少出现一次,比如匹配连续的数字,\d+可以匹配像12345678等连续数字的字符串。?表示匹配一次或零次,在处理一些可能有后缀的文件名时,比如readme.txtreadmereadme\.txt?就可以同时匹配这两种情况,txt后的?表示txt这个后缀可以出现一次或不出现。{m,n}表示至少重复m次,至多重复n次,a{1,3}匹配aaaaaa ;在解析网页标签属性时,假设某个属性的值允许 1 到 3 个字母,[a-zA-Z]{1,3}就可以用来匹配该属性值。{m}表示与前一项完全匹配m次,a{2}只匹配aa,在处理固定格式的验证码时,如果验证码是两位相同的数字,\d{2}(这里假设验证码是数字)就可以用来验证格式是否正确。

  • 位置相关元字符^在默认情况下匹配字符串开头,在检查用户输入的命令是否以特定单词开头时,比如判断用户输入是否是"search "开头,^search\s就能实现这个功能,其中\s表示匹配空白字符。在re.MULTILINE模式下还可匹配每行开头,在处理日志文件时,每行日志都有一个时间戳,格式为[年-月-日 时:分:秒],要提取每行日志的时间戳,re.findall(r'^\[\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\]', log_text, re.MULTILINE)就可以做到。$匹配行末尾,在re.MULTILINE模式下还可匹配每行末尾,World$匹配以World结尾的字符串。在处理配置文件时,假设配置项以=value结尾,=value$就可以用来查找这类配置项。\A仅匹配字符串开头,\Z只匹配字符串尾。在验证用户输入的完整字符串是否是特定内容时,\Ahello\Z可以精确匹配字符串hello,多一个或少一个字符都无法匹配。\b是字边界,匹配单词开头或结尾,\bword\b精确匹配单词word ,在文本编辑软件中,实现查找某个单词功能时,\b可以确保只匹配完整的单词,而不是单词的一部分,比如查找"the",不会匹配到"thesis"中的"the"\B\b相反,匹配不在字边界的位置,在处理一些缩写词时,假设要匹配缩写词内部的字符,而不是单词边界上的字符,就可以使用\B ,比如\BMr\B可以匹配"Mr."中的"Mr",但不会匹配单独的"Mr"单词。

  • 逻辑相关元字符|是 “或” 运算符,在一个处理多种文件类型的程序中,需要匹配图片文件的扩展名,jpg|png|gif就可以匹配jpgpnggif这三种扩展名,用来判断文件是否为图片文件。

  • 其他元字符\用于转义元字符,使元字符匹配自身,如\[匹配[ ;还用于表示特殊序列。在解析 LaTeX 公式时,经常会遇到需要匹配特殊符号的情况,比如匹配\sum这个符号,就需要使用r'\\sum',这里第一个\是 Python 字符串转义,第二个\是正则表达式转义,确保匹配到\sum.匹配除换行符外的任何字符,在re.DOTALL模式下可匹配换行符,a.b可匹配ab之间有任意一个字符(除换行符)的情况,在re.DOTALL模式下也可匹配包含换行符的情况。在处理一些文本片段时,如果要匹配ab之间有任意字符(包括换行符)的情况,在设置re.DOTALL标志后,re.search('a.*b', text_with_newline, re.DOTALL)就可以实现。

重复匹配

  • 重复元字符*表示前一个字符可匹配零次或更多次,如ca*t可匹配ctcatcaaat等;+表示匹配一次或更多次,如ca+t可匹配catcaaat,但不能匹配ct?表示匹配一次或零次,如home-?brew可匹配homebrewhome-brew{m,n}表示至少重复m次,至多重复n次,如a/{1,3}b匹配a/ba//ba///b{m}表示与前一项完全匹配m次,如a/{2}b只匹配a//b

  • 贪婪与非贪婪匹配:重复匹配默认是贪婪的,匹配引擎会尽可能多地匹配,若后续部分不匹配则回退重试。如a[bcd]*b匹配abcbd时,先尽可能多地匹配[bcd]*,失败后逐步回退。非贪婪匹配使用*?+???{m,n}?,会尽可能少地匹配文本。如匹配 HTML 标签<.*>会匹配整个字符串,而<.*?>则只匹配第一个标签 。

在 Python 中使用正则表达式

  • 编译正则表达式:使用re.compile()将正则表达式编译为模式对象,模式对象有多种操作方法。如p = re.compile('ab*') ,还可传入flags参数启用特殊功能,如p = re.compile('ab*', re.IGNORECASE)实现不区分大小写匹配。由于正则表达式中反斜杠与 Python 字符串转义冲突,建议使用原始字符串表示法,如r"\section"

  • 应用匹配

    • 匹配方法:模式对象的match()用于确定正则是否从字符串开头匹配,search()用于扫描字符串查找匹配位置,findall()返回所有匹配子字符串的列表,finditer()返回匹配对象的迭代器。若未找到匹配,match()search()返回None,成功则返回匹配对象,包含匹配相关信息 。

    • 匹配对象属性和方法:匹配对象的group()返回匹配的字符串,start()返回匹配开始位置,end()返回匹配结束位置,span()返回包含开始和结束位置的元组 。

  • 模块级函数re模块提供的match()search()findall()sub()等顶级函数,功能与模式对象方法类似,只是将正则字符串作为第一个参数,并会缓存编译对象。循环中使用正则表达式时,预编译可节省函数调用开销;循环外使用,两者差异不大。

  • 编译标志:编译标志可修改正则表达式的工作方式,如re.IGNORECASE实现不区分大小写匹配,re.DOTALL使.匹配包括换行符在内的任何字符,re.VERBOSE允许编写更易读的正则表达式,忽略正则字符串中的空格(字符类中或反斜杠前的空格除外),并支持添加注释。

编译标志含义示例
re.ASCII/re.A使\w\b\s\d等只匹配 ASCII 字符re.compile(r'\w+', re.ASCII),只匹配 ASCII 字母数字字符
re.DOTALL/re.S使.匹配任何字符,包括换行符re.compile(r'.*', re.DOTALL),可匹配包含换行符的字符串
re.IGNORECASE/re.I进行大小写不敏感匹配re.compile(r'[A-Z]', re.IGNORECASE),可匹配大小写字母
re.LOCALE/re.L进行区域设置感知匹配(Python 3 中不鼓励使用)在特定区域设置下,\w匹配特定区域的字母字符
re.MULTILINE/re.M多行匹配,影响^$re.compile(r'^From', re.MULTILINE),可匹配每行开头的From
re.VERBOSE/re.X启用详细的正则表达式,忽略空格和注释re.compile(r'\s*(?P<header>[^:]+)\s*:(?P<value>.*?)\s*$', re.VERBOSE)

更多模式能力

  • 更多元字符|是 “或” 运算符,如Crow|Servo匹配CrowServo^在默认情况下匹配字符串开头,在re.MULTILINE模式下还可匹配每行开头;$匹配行末尾,在re.MULTILINE模式下还可匹配每行末尾;\A仅匹配字符串开头;\Z只匹配字符串尾;\b是字边界,匹配单词开头或结尾;\B\b相反,匹配不在字边界的位置。

  • 分组:用()标记分组,分组可捕获匹配文本的索引,组从 0 开始编号,组 0 表示整个正则。如(a)b,匹配对象的group(0)返回整个匹配字符串,group(1)返回第一个分组匹配的字符串。还可使用后向引用,如\b(\w+)\s+\1\b检测重复单词 。

  • 非捕获和命名组:非捕获组(?:...)用于表示正则的一部分,但不捕获匹配内容,可在不改变其他组编号的情况下添加新组。命名组(?P<name>...)通过名称引用组,方便记忆和使用,如re.compile(r'(?P<word>\b\w+\b)'),匹配对象可用group('word')获取匹配内容,还可通过groupdict()将命名分组提取为字典。

  • 前视断言:前视断言有肯定型(?=…)和否定型(?!…) 。肯定型前视断言内部表达式匹配则成功,但引擎不向前推进;否定型前视断言内部表达式不匹配则成功。如匹配扩展名不是bat的文件名,可用.*[.](?!bat$)[^.]*$

修改字符串

  • 分割字符串:模式对象的split()方法根据正则匹配拆分字符串,返回片段列表,可限制拆分次数。若正则中有捕获括号,括号内的内容也会作为列表一部分返回。re.split()是模块级函数,功能类似 。

  • 搜索和替换sub()方法用指定字符串替换匹配的子字符串,可指定替换次数;subn()方法返回替换后的字符串和替换次数。replacement可以是字符串或函数,若是字符串,其中的反斜杠转义会被处理,后向引用会替换为相应组匹配的子字符串;若是函数,每次匹配会调用该函数,函数根据匹配对象计算替换字符串 。

实际项目应用案例

  • 数据清洗项目:在一个文本数据分析项目中,需要从大量的用户评论数据中提取有用信息并清洗数据。评论数据包含各种格式不规范的内容,如包含特殊字符、HTML 标签等。利用正则表达式可去除 HTML 标签,如使用re.sub(r'<.*?>', '', text) ,其中<.*?>匹配所有 HTML 标签,将其替换为空字符串。还可以提取特定格式的数据,如提取评论中的邮箱地址,使用re.findall(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', text) ,该正则表达式通过分组和字符类等元字符,精确匹配符合邮箱格式的字符串。

  • 日志分析项目:在服务器日志分析场景中,日志文件记录了大量的访问信息。要统计特定 IP 地址的访问次数,可以用re.findall(r'\b(?:\d{1,3}\.){3}\d{1,3}\b', log_text)提取日志中的 IP 地址,再进行计数统计。若要分析访问的 URL 路径,可使用re.findall(r'GET\s+([^ ]+)', log_text) ,其中GET是 HTTP 请求方法,([^ ]+)分组捕获 URL 路径,通过这种方式可以了解用户对不同页面的访问情况,为优化网站提供数据支持。

  • 代码检查工具开发:开发一个代码检查工具,用于检查 Python 代码中的函数命名是否符合规范(假设规范为函数名只能包含小写字母、数字和下划线,且不能以数字开头)。可以使用re.findall(r'\bdef\s+([a-z_][a-z0-9_]*)\s*\(', code_text)来查找代码中的函数定义,并通过正则表达式判断函数名是否符合规范。若不符合,可提示开发者进行修改,提高代码的规范性和可读性。

常见问题

  1. 使用字符串方法:处理固定字符串或单个字符类且不使用re模块功能时,使用字符串自身的方法(如replace()translate())可能更高效,应优先考虑。例如,将字符串中的所有空格替换为下划线,使用字符串的replace方法"hello world".replace(" ", "_"),代码简洁且执行效率高。但如果涉及复杂的匹配模式,如替换所有连续出现两次及以上的空格为单个下划线,就需要借助正则表达式re.sub(r' {2,}', ' ', "hello world today")来实现。

  2. match () 和 search () 的区别match()只检查正则是否从字符串开头匹配,search()会扫描整个字符串查找匹配项。不要为了让match()实现search()的功能而在正则前添加.*,应直接使用search()。例如,在查找字符串"this is a test"中是否包含"is"时,使用re.match('is', "this is a test")会返回None,因为match从字符串开头匹配,而re.search('is', "this is a test")能正确找到匹配项并返回相应的匹配对象。

  3. 贪婪与非贪婪:注意重复匹配的贪婪和非贪婪模式,处理 HTML 标签等需要精确匹配的场景时,使用非贪婪限定符避免匹配过多内容。比如匹配 HTML 段落标签<p>content</p>,若使用贪婪模式re.match('<p>.*</p>', "<p>first</p><p>second</p>"),会匹配整个包含两个段落的字符串;而使用非贪婪模式re.match('<p>.*?</p>', "<p>first</p><p>second</p>"),则只会匹配第一个段落标签及其内容。

  4. 使用 re.VERBOSE:复杂正则表达式可读性差,使用re.VERBOSE标志可通过忽略空格和添加注释来提高可读性。例如,匹配 IP 地址的正则表达式r'((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)',使用re.VERBOSE后可以写成:

import re
ip_pattern = re.compile(r"""(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)  # 匹配0 - 255之间的数字\.                                      # 匹配点号(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)  # 匹配0 - 255之间的数字\.                                      # 匹配点号(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)  # 匹配0 - 255之间的数字\.                                      # 匹配点号(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)  # 匹配0 - 255之间的数字
""", re.VERBOSE)

这样更易理解和维护。

总结

本文全面且深入地介绍了 Python 中re模块的正则表达式用法。从基础概念出发,详细讲解了匹配字符、元字符的各种用法;深入探讨了重复匹配的机制,包括贪婪与非贪婪模式;全面阐述了在 Python 中使用正则表达式的具体方式,涵盖编译、匹配、修改字符串等操作;还介绍了更多模式能力,如分组、断言等高级特性;通过数据清洗、日志分析、代码检查等实际项目案例,展示了正则表达式在真实场景中的强大应用;最后总结了常见问题及解决方法。正则表达式功能强大,但使用时需谨慎,开发者应在实践中不断积累经验,根据具体需求灵活运用各种技巧,从而高效地完成文本处理任务。

TAG:Python;正则表达式;re 模块;字符串处理;元字符;重复匹配;分组;前视断言;数据清洗;日志分析;代码检查

相关学习资源

  1. 官方文档:Python 官方 re 模块文档,详细介绍了re模块的函数、类和正则表达式语法,是深入学习的基础资料。

  2. 在线教程:RegexOne,提供了丰富的交互式正则表达式练习,通过实际操作帮助初学者快速上手,加深对正则表达式的理解。

  3. 书籍:《精通正则表达式》,深入讲解正则表达式的原理、高级应用和优化技巧,适合想要进一步提升正则表达式运用能力的读者。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词