Python正则表达式
print(f"提取的所有数字部分: {all_nums}") # ['138', '1234', '5678', '888']:我要找“一个以 T 开头,后面跟着几个小写字母,最后以 i 结尾的词”。# 剔除所有 HTML 标签:匹配 < 开头,中间非 > 的内容,> 结尾。解决的问题,就不要动用正则这门“大炮”,这体现了你对代码可维护性的考量。这是正则里最容易翻车的地方,也是 AI 爬虫处理
正则表达式的核心哲学
正则表达式本质上是一种描述文本模式的特殊语法。它独立于编程语言,你在 Python、Java、Scala 甚至是 Linux 的 grep 命令里看到的逻辑几乎是一通百通的。
-
普通搜索:我要找“xxx”。(只能找固定的词)
-
正则搜索:我要找“一个以 T 开头,后面跟着几个小写字母,最后以 i 结尾的词”。(能找一类符合规则的词)
元字符:正则的建筑材料
元字符是构成正则最基础的符号,就像是建筑里的砖块。
| 符号 | 含义 | 形象理解 |
|---|---|---|
. |
匹配除换行符以外的任意单个字符 | 万能代金券 |
\d |
匹配一个数字 (0-9) | "d" 代表 digit |
\D |
匹配一个非数字 | 大写字母通常表示“反义” |
\w |
匹配字母、数字或下划线 | "w" 代表 word |
\s |
匹配空白字符(空格、制表符等) | "s" 代表 space |
^ |
匹配字符串的开头 | 守门员 |
$ |
匹配字符串的结尾 | 扫尾员 |
[abc] |
匹配 a、b 或 c 中的任意一个 | 选秀池 |
[^abc] |
匹配除了 a、b、c 以外的字符 | 排除名单 |
量词:控制出现的次数
量词决定了前面的字符“连续出现几次”,这在匹配手机号、时间戳时非常有用。
| 符号 | 含义 | 例子 |
|---|---|---|
* |
出现 0 次或多次 | \d* (可能有数字,也可能没有) |
+ |
出现 1 次或多次 | \d+ (至少得有一个数字) |
? |
出现 0 次或 1 次 | https? (匹配 http 或 https) |
{n} |
精确出现 n 次 | \d{11} (匹配手机号) |
{n,m} |
出现 n 到 m 次 | \w{6,12} (匹配 6-12 位密码) |
Python re 模块实战
Python 通过内置的 re 模块来支持正则。作为大数据开发者,你需要熟练掌握这几个核心方法。
import re
# 待处理的原始字符串
text = "Timi's phone is 138-1234-5678, his ID is T888."
# 1. re.search(): 在全文找第一个匹配项
# pattern: 匹配规则 (str 类型,建议加 r 前缀防止转义)
# string: 待搜字符串
# 返回值: Match 对象(找到)或 None(没找到)
result = re.search(r"\d{3}-\d{4}-\d{4}", text)
if result:
# .group() 用于提取匹配到的字符串内容
print(f"搜到了电话: {result.group()}")
# 2. re.findall(): 找全文所有的匹配,直接返回列表
## 注意事项: 全文直接进内存!! 大数据改用 finditer
# 适合提取日志里所有的报错代码或 IP 地址
all_nums = re.findall(r"\d+", text)
print(f"提取的所有数字部分: {all_nums}") # ['138', '1234', '5678', '888']
# 3. re.match(): 仅匹配首字符
fisrt = re.match(r'/w','text')
print(f'首字母是: {first.group()}')
# 4. re.sub(): 替换(数据脱敏、文本清洗常用)
# replacement: 替换后的内容
# 把电话中间四位换成 ****
# \1 和 \2 代表引用后面括号里捕获的分组
secret_text = re.sub(r"(\d{3})-\d{4}-(\d{4})", r"\1-****-\2", text)
print(f"脱敏后: {secret_text}")
贪婪与非贪婪:面试重灾区
这是正则里最容易翻车的地方,也是 AI 爬虫处理 HTML 时的必考点。
-
贪婪模式(默认):尽可能多地匹配。
-
正则:
a.*b -
文本:
axxxbxxxb -
结果:
axxxbxxxb(一口气吞到最后一个 b)
-
-
非贪婪模式(加个
?):见好就收,尽可能少地匹配。-
正则:
a.*?b -
结果:
axxxb(遇到第一个 b 就停下)
-
AI 场景应用:在提取标签内容时(如 <div>内容</div>),如果不加 ? 变成非贪婪,你可能会把整个网页的所有 div 连在一起一次性全抓出来。
分组与捕获:精准手术刀
用小括号 () 可以把正则分成几个小组,方便我们精准提取。
log = "2023-10-01 ERROR: Connection Timeout"
# 提取日期和错误等级
# (?P<name>...) 是给小组起名字,让代码更易读
pattern = r"(?P<date>\d{4}-\d{2}-\d{2}) (?P<level>\w+):"
match = re.search(pattern, log)
if match:
# 通过名字提取,比通过索引 [1] 更有工程美感
print(match.group("date")) # 2023-10-01
print(match.group("level")) # ERROR
大数据与 AI 场景下的实战
日志清洗与过滤
当你流式读取那个 10G 的文件时,可以用正则快速过滤掉无效信息。
def log_filter(file_path): # 预编译正则:在大规模循环中,提前编译速度快 10% 以上 # re.compile 会生成一个正则对象,多次使用时效率极高 error_pattern = re.compile(r"ERROR|CRITICAL") with open(file_path, 'r', encoding='utf-8') as f: for line in f: if error_pattern.search(line): yield line.strip()
AI 语料清洗
在给大模型(LLM)喂数据前,需要剔除 HTML 标签、特殊符号或隐私信息。
raw_html = "<p>Hello <b>Timi</b>!</p>" # 剔除所有 HTML 标签:匹配 < 开头,中间非 > 的内容,> 结尾 clean_text = re.sub(r"<[^>]+>", "", raw_html) print(clean_text) # Hello Timi!
性能优化与面试避坑指南
关于 ReDoS(正则表达式拒绝服务攻击)
面试官可能会问:正则会有性能问题吗?
-
回答:会有。如果编写了糟糕的正则(比如嵌套了大量的
+或*,如(a+)+$),会导致回溯(Backtracking)次数指数级增长,消耗大量 CPU。在大数据处理中,我会优先使用re.compile()预编译模式,并尽量使用非贪婪匹配或确定的字符集来减少回溯风险。
原生字符串的使用
在写正则时,永远记得在字符串前加 r(如 r"\d")。否则 Python 的转义字符(如 \n 代表换行)会和正则的转义冲突。
替代方案
正则虽然强大,但可读性较差。如果能用内置的 str.startswith()、str.endswith() 或者 json.loads() 解决的问题,就不要动用正则这门“大炮”,这体现了你对代码可维护性的考量。
更多推荐


所有评论(0)