首页 / 资讯中心 / 文章详情

正则表达式入门:从模式匹配到文本提取的实战指南

正则表达式入门:从模式匹配到文本提取的实战指南 ★ FEATURED ARTICLE
简介这份资源是面向Python初学者与进阶学习者的正则表达式专题学习资料以PDF文档形式呈现适合正在系统学习Python文本处理、数据清洗或爬虫开发的读者用于补齐正则匹配与提取这一关键技能点。压缩包内共1个PDF文件大小约661KB内容围绕正则表达式的基础语法与实战应用展开涵盖元字符、字符集、量词、分组捕获、贪婪与非贪婪匹配等核心知识点并配有Python中re模块常用函数的用法说明与示例。目前已有260人学习下载说明该主题在Python学习路径中具有稳定的关注度。读者可通过这份文档快速建立正则表达式的知识框架掌握在字符串查找、替换、校验等场景下的实际写法为后续处理日志解析、表单验证、网页信息抽取等任务打下基础也可作为日常查阅的速查参考。1. 正则表达式到底在干嘛一个“找东西”的万能公式你有没有过这种经历在一份几千行的日志里想找出所有带“error”的行或者在一堆用户填的手机号里挑出格式不对的那些。手动翻眼睛会瞎。用查找替换又不够灵活。这时候正则表达式就该出场了。通俗地说正则表达式就是一套用来描述“文字长什么样”的公式。它不是具体的某段文字而是一个模式。比如你想找“三个数字后面跟一个横杠再跟四个数字”你不用把每个可能的号码都列出来只需要写一个模式让程序拿着这个模式去文本里“对号入座”。它存在的理由很简单人找文字靠眼睛和直觉计算机找文字靠规则而正则就是人和计算机之间关于“文字规则”的通用语言。搞懂它你就能让程序帮你干那些枯燥又容易看走眼的文本筛选活儿。2. 为什么非得用正则从“笨办法”到“聪明模式”2.1 没有正则的时候我们是怎么找文本的假设你手里有一份系统日志想找出所有包含“登录失败”的行。最直接的办法是写个循环逐行判断if 登录失败 in line。这招在关键词固定的时候挺好用代码也直白。但需求稍微一变麻烦就来了如果“登录失败”中间可能夹着空格或者“登录”和“失败”之间还有别的字比如“登录验证失败”“登录尝试失败”这个简单的包含判断就歇菜了。你可能会想到用line.find(登录)和line.find(失败)分别找位置再比较先后顺序代码立刻变得又长又容易出错。这就是没有正则时的典型困境每多一种变化就得多写一堆判断逻辑维护起来像在补一件到处是洞的衣服。2.2 正则的“模式思维”一次描述到处匹配正则换了个思路。它不关心具体是“登录失败”还是“登录验证失败”它只关心“登录”和“失败”这两个词是否按顺序出现中间隔了什么都行。用正则写出来就是登录.*失败。这里的.*就像一个占位符意思是“这里可以有任意多个任意字符”。你看原本需要好几行代码才能说清的事一个模式就搞定了。这种“描述规则”的能力让正则特别擅长处理那些“大概长这样但细节有变化”的文本。比如从网页源码里提取所有链接、从配置文件里抓出所有 IP 地址、验证用户输入的邮箱格式对不对这些都是正则的拿手好戏。2.3 一个最小可用的例子把手机号从文本里揪出来光说概念有点飘看个具体例子。假设有一段文字里面混着手机号和其它数字我们想把 11 位的手机号找出来。手机号的规则是1 开头第二位通常是 3 到 9后面跟着 9 个数字。用正则描述就是1[3-9]\d{9}。拆开看1就是字面的数字 1[3-9]表示这一位可以是 3 到 9 中的任意一个数字\d代表任意一个数字{9}表示前面那个\d要重复 9 次。合起来就是“1 开头第二位 3 到 9后面再跟 9 个数字”正好 11 位。import re text 联系我13812345678备用12345678901座机010-88886666 # 定义手机号模式1开头第二位3-9后面9个数字 pattern r1[3-9]\d{9} phones re.findall(pattern, text) print(phones) # 输出[13812345678]这段代码里re.findall的作用是把文本里所有符合模式的部分都找出来返回一个列表。pattern前面的r表示这是一个原始字符串避免反斜杠被 Python 提前转义。运行结果是只找到了13812345678因为12345678901虽然也是 11 位但第二位是 2不符合[3-9]的规则。你看正则帮我们自动完成了“筛选”这个动作我们只需要把规则说清楚就行。3. 正则的常用“零件”元字符、量词和分组3.1 元字符那些有特殊含义的符号正则里有一批符号不表示它们本身而是表示一类字符或一种位置这些符号叫元字符。最常见的几个.表示任意一个字符默认不包括换行\d表示任意一个数字等价于[0-9]\w表示字母、数字或下划线\s表示空白字符包括空格、制表符。还有^和$分别表示一行的开头和结尾。比如^\d$就表示“整行必须全部是数字不能有别的”。这些元字符是构成模式的基本积木记住它们你就能拼出大部分日常需要的规则。3.2 量词控制“重复几次”的开关光有元字符还不够我们经常需要表达“重复若干次”。量词就是干这个的。*表示前面的东西出现 0 次或多次表示 1 次或多次?表示 0 次或 1 次{n}表示恰好 n 次{n,m}表示 n 到 m 次。举个例子\d表示“一个或多个数字”可以匹配1、123、9999。而\d{3,5}表示“3 到 5 个数字”能匹配123、1234、12345但不会匹配12或123456。量词默认是“贪婪”的也就是尽可能多匹配。比如对字符串aaa用a它会一口气匹配全部三个 a。如果在量词后面加个?比如a?就变成“懒惰”模式尽可能少匹配只匹配一个 a 就收手。这个区别在提取 HTML 标签内容时特别有用后面会提到。3.3 分组与捕获把匹配到的内容“拎出来”有时候我们不只是想知道“有没有匹配”还想把匹配到的某一部分单独取出来。这时候就用圆括号()把需要提取的部分括起来这叫分组。分组匹配到的内容会被“捕获”可以通过编号或名字来引用。比如从日期2025-03-21里分别提取年、月、日可以写成(\d{4})-(\d{2})-(\d{2})。第一个括号捕获年份第二个捕获月份第三个捕获日期。在 Python 的re模块里用group(1)、group(2)就能拿到这些部分。import re date_str 今天是2025-03-21明天是2025-03-22 # 三个分组分别对应年、月、日 pattern r(\d{4})-(\d{2})-(\d{2}) matches re.finditer(pattern, date_str) for m in matches: print(f年{m.group(1)}月{m.group(2)}日{m.group(3)}) # 输出 # 年2025月03日21 # 年2025月03日22re.finditer返回一个迭代器每次拿出一个匹配对象。group(1)到group(3)分别对应三个括号里的内容。如果不分组整个匹配到的字符串可以用group(0)拿到。分组让正则从“只判断有没有”升级到“还能提取关键信息”实用性大大增强。4. 容易搞混的几个概念别把正则当通配符4.1 易混点一正则的*和文件通配符的*很多人第一次接触正则是在命令行里用ls *.txt以为*就是“任意字符”。但在正则里*是量词表示“前面的东西重复 0 次或多次”它不能单独使用。*.txt在正则里是错的因为*前面没有东西可重复。正则里表示“任意字符”的是.所以“任意字符重复多次再跟 .txt”应该写成.*\.txt。注意那个\.因为.在正则里是元字符要匹配真正的点号必须用反斜杠转义。这个区别坑过不少人记住通配符的*代表任意字符正则的*代表重复次数。4.2 易混点二^和$在多行模式下的行为^匹配字符串开头$匹配字符串结尾这是默认行为。但如果你处理的是多行文本想让^和$匹配每一行的开头和结尾就需要开启多行模式。在 Python 里给re.compile或re.findall传一个re.MULTILINE标志就行。不开多行模式时^只认整个文本的第一个字符位置$只认最后一个字符位置。开了之后每个换行符后面的位置都被视为行首每个换行符前面的位置被视为行尾。这个细节在逐行分析日志时特别关键忘了开多行模式匹配结果会少得让你怀疑人生。4.3 易混点三贪婪匹配和懒惰匹配前面提过量词默认贪婪但很多人第一次遇到时还是会懵。比如要从div内容/divdiv更多/div里提取第一个 div 的内容用div.*/div会一口气匹配到最后一个/div因为.*贪婪地吃掉了中间所有的东西。改成div.*?/div.*?变成懒惰模式匹配到第一个/div就停。这个?加在量词后面就是“别贪心见好就收”的意思。处理 HTML 或 XML 片段时懒惰匹配几乎是必备技巧否则提取出来的东西会比你想要的长一大截。4.4 易混点四match和search的区别Python 的re模块里re.match和re.search长得像行为却不同。re.match只从字符串开头开始尝试匹配如果开头对不上就直接返回None。re.search则会扫描整个字符串找到第一个匹配的位置就返回。举个例子对字符串abc123用模式\dre.match返回None因为开头是字母不是数字re.search则返回123。很多人写代码时随手用了match结果明明文本里有目标却死活匹配不到排查半天才发现是起点问题。想在整个字符串里找就用search或findall。4.5 易混点五转义字符的“套娃”正则里用反斜杠\来转义元字符比如\.表示真正的点号。但在 Python 字符串里反斜杠本身也有转义含义。如果你写\dPython 会先处理字符串转义发现\d不是合法转义序列可能会报警告或直接保留。为了省心写正则时一律用原始字符串r\d这样 Python 就不插手直接把\d原样交给正则引擎。这个习惯能帮你避开很多莫名其妙的报错尤其是模式里包含\b、\n这类既是正则元字符又是字符串转义符的情况。5. 什么时候该用正则什么时候该绕开正则是个好工具但不是万能锤。判断标准很简单看你的文本有没有“规律”以及这个规律复不复杂。适合用的场景格式验证比如检查用户输入的邮箱、手机号、身份证号是否符合基本格式批量提取比如从一堆日志里抓出所有 IP 地址、时间戳、订单号简单替换比如把文本里所有连续多个空格换成一个空格。这些场景的共同点是规则清晰、文本结构不嵌套。不适合用的场景解析 HTML 或 JSON 这种嵌套结构。正则处理嵌套能力很弱写出来的模式又长又难维护还容易漏掉边界情况。这种活儿应该交给专门的解析库比如解析 HTML 用 BeautifulSoup解析 JSON 用json模块。另外如果只是找固定字符串比如在一段文字里找“你好”直接用in判断或者str.find就够了没必要上正则杀鸡用牛刀反而让代码更难读。我自己的习惯是动手写正则之前先问自己三个问题——文本有规律吗规律能用一两行说清吗需要提取或替换吗三个都是“是”就放心用正则只要有一个“否”就停下来想想有没有更合适的工具。有一次我图省事用正则去解析一个结构稍微复杂的配置文件结果模式越写越长最后自己都看不懂了调试花了两个小时。从那以后我每次写超过一行的正则都强制先拿几条真实数据跑一遍re.findall看看结果确认没问题再放进代码里。希望这个习惯也能帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站