小白python入门 - 23. Python 正则表达式的应用
2026/7/23 3:31:48 网站建设 项目流程

正则表达式的应用

1. 正则表达式概述

处理文本时,常需要按某种“规则”检查、提取或改写片段,例如从日志里找出订单号、校验表单字段格式、把敏感数字中间位打码。正则表达式(Regular Expression)就是描述这类规则的专用记法:它定义一种模式,用来判断字符串是否匹配,或从字符串中取出/替换匹配部分。

可以把它理解成比文件名通配符(*?)更精细的匹配语言:表达力更强,书写成本也更高。今天绝大多数语言都内置了正则支持;在 Python 中,标准库模块re负责编译与匹配。

更多语法可参考通用入门材料,例如 正则表达式 30 分钟入门。读完后,下表中的常用符号会更容易对照使用。

符号含义示例说明
.任意单个字符c.t可匹配catc9t
\w字母、数字、下划线\w+一段“词”字符
\s空白(空格、制表、换行等)id\s*=id=之间允许空白
\d数字\d{4}恰好 4 位数字
\b单词边界\bEND\b独立单词END
^/$串首 / 串尾^ERR\.log$以 ERR 开头、以 .log 结尾
\W\S\D\B与上面几类相反\D+连续非数字
[...]/[^...]字符集 / 取反[A-Z][^0-9]大写字母;非数字
*/+/?0 次及以上 / 1 次及以上 / 0 或 1 次\d+至少一位数字
{n}{m,}{m,n}固定或区间次数\d{2,4}2~4 位数字
|分支(或)GET|POST匹配其一
(exp)捕获分组(\d+)-(\d+)可取各组内容
(?:exp)非捕获分组(?:ab)+只分组不捕获
(?=exp)/(?<=exp)正向 / 反向先行断言\d+(?=元)数字后紧跟“元”
(?!exp)/(?<!exp)负向断言(?<!\d)\d{6}(?!\d)恰好 6 位且两侧非数字
*?+???{m,n}?懒惰量词a.*?b尽可能短地匹配

说明:若要匹配正则元字符本身,需转义,例如字面小数点写作\.,字面括号写作\(\)


2. Python 中的re模块

函数 / 标记作用
compile(pattern, flags=0)编译模式,得到可复用的正则对象
match(pattern, string, flags=0)字符串开头尝试匹配,成功返回匹配对象,否则None
fullmatch(pattern, string, flags=0)要求整串完全符合模式
search(pattern, string, flags=0)在串中查找第一次出现
findall(pattern, string, flags=0)返回所有匹配的字符串列表(有分组时结构会变化)
finditer(pattern, string, flags=0)返回匹配对象的迭代器
split(pattern, string, maxsplit=0, flags=0)按模式切分,返回列表
sub(pattern, repl, string, count=0, flags=0)用替换内容替换匹配;repl可为字符串或函数
purge()清理隐式编译缓存
re.I/re.IGNORECASE忽略大小写
re.M/re.MULTILINE多行模式下^$作用于每行

关键概念:

  • 同一模式若会多次使用,应先compile,再调用对象的match/search/findall等方法。
  • 书写模式时推荐原始字符串r'...',避免\被 Python 字符串先转义一层(否则\d常要写成\\d)。

多个flags可用按位或组合,例如flags=re.I | re.M


3. 应用示例

3.1 校验工号与邮箱(match/fullmatch

规则约定:

  • 工号:2 位大写字母 + 4~6 位数字,整串合法(如HR1024IT90001)。
  • 邮箱:本地部分允许字母数字、点、下划线、百分号、加号、减号;@后为域名片段。
importre staff_id=input('工号: ').strip()email=input('邮箱: ').strip()# match:从开头匹配;配合 ^...$ 等价于“整串符合”m_id=re.match(r'^[A-Z]{2}\d{4,6}$',staff_id)ifnotm_id:print('工号格式无效')# fullmatch:整串必须完全匹配,模式里可不写 ^ $m_mail=re.fullmatch(r'[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}',email,)ifnotm_mail:print('邮箱格式无效')ifm_idandm_mail:print('校验通过')

提示:match只锚定开头;若未写$AB1234xyz在宽松模式下可能被误判为“从开头已匹配成功”。校验整字段时优先fullmatch,或显式使用^...$


3.2 从日志中提取订单号(compile/findall/finditer/search

订单号形如ORD-+ 8 位数字。用前后断言避免与更长数字串粘连,并演示三种取结果的方式。

importre# 左侧非数字、右侧非数字,降低误匹配pattern=re.compile(r'(?<!\d)ORD-\d{8}(?!\d)')log_text=""" [INFO] create ORD-20250101 ok retry ORD-20250102; noise ORD-20250102111 ignored client sent ORD-20250315 and ORD-20250316 """# 方法一:全部匹配成列表print(re.findall(pattern,log_text))# 方法二:迭代匹配对象forminpattern.finditer(log_text):print(m.group(),'at',m.start())# 方法三:search 从上次结束位置继续扫m=pattern.search(log_text)whilem:print(m.group())m=pattern.search(log_text,m.end())

关键点:

  • findall适合只要文本;需要位置或分组细节时用finditer
  • search(..., pos)可从指定下标继续搜,适合手写扫描循环。

若号段规则更复杂,可把主体改成分支,例如ORD-(?:20\d{6}|9\d{7}),再保留两侧断言。


3.3 脱敏证件号与手机号(sub

将 11 位手机号中间 4 位、18 位证件号中间若干位替换为*repl使用函数,按分组拼接。

importredefmask_sensitive(text:str)->str:defrepl_phone(m:re.Match)->str:s=m.group()returns[:3]+'****'+s[7:]defrepl_id(m:re.Match)->str:s=m.group()returns[:4]+'*'*10+s[-4:]text=re.sub(r'(?<!\d)1\d{10}(?!\d)',repl_phone,text)text=re.sub(r'(?<!\d)\d{17}[\dXx](?!\d)',repl_id,text,flags=re.IGNORECASE,)returntext sample='联系人 13812345678,证件 110101199001011234,备用 13900001111'print(mask_sensitive(sample))# 输出类似:联系人 138****5678,证件 1101**********1234,备用 139****1111

说明:flags=re.I(或re.IGNORECASE)让证件末位x/X都能匹配。多个标志用|叠加。真实业务号段、校验位规则更严,此处仅演示替换接口。


3.4 按多种分隔符拆分配置行(split

配置项可能用逗号、分号或竖线分隔,分隔符后允许空格。

importre line='host=10.0.0.8; port=8080 | timeout=3, retries=2'parts=re.split(r'[,;|]\s*',line)fields=[pforpinpartsifp]foriteminfields:print(item)# host=10.0.0.8# port=8080# timeout=3# retries=2

split得到的列表可能含空串(首尾或连续分隔符),用列表推导过滤即可。需要限制段数时传入maxsplit


总结

场景常用接口
整字段是否合法fullmatch,或match+^...$
取出全部片段findall/finditer
从某位置继续找search+ 结束下标
改写匹配内容sub(字符串或回调)
按模式切开split
模式复用compile

正则擅长结构化文本的校验、抽取与改写;模式越复杂,越建议用在线调试工具边写边测。业务规则变更时,优先收紧字符类与断言,并补上边界用例(空串、粘连数字、大小写),避免“能跑但误伤”。
`)

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询