str.contains 默认启用正则模式,反斜杠被当作转义符导致匹配失败;应设 regex=False 或用原始字符串双写反斜杠;str.replace 仅替换不提取,提取需用 str.extract 或 str.findall;清洗混合符号需分步处理 HTML 实体、不可见字符等。

str.contains 为什么匹配不到带反斜杠的字符串
因为 str.contains 默认开启正则模式,而反斜杠 在正则里是转义符,不是字面量。比如想查路径中是否含 "C:Users",直接传进去会被正则引擎当成非法转义(U 不合法),抛出 re.error: bad escape。
- 最稳妥的做法是加参数
regex=False,强制按字面匹配:s.str.contains(r"C:Users", regex=False) - 如果真要用正则(比如模糊匹配路径分隔符),得用原始字符串 + 双反斜杠:
s.str.contains(r"C:\Users")—— 注意r""防止 Python 层吃掉一个,正则层还得留一个 - Windows 路径建议统一用正斜杠或
os.path.normpath预处理,避免被正则误伤
str.replace 用正则提取内容时,为什么只替换不提取
str.replace 是替换函数,不是提取函数。它返回新字符串,不会自动捕获括号里的分组内容。想“提取”必须配合 str.extract 或 str.findall。
- 错误写法:
s.str.replace(r"ID:(d+)", r"")—— 这只是把ID:123换成123,但没告诉你原字符串有没有匹配 - 正确提取用:
s.str.extract(r"ID:(d+)"),返回 DataFrame,每列对应一个捕获组 - 如果一行可能有多个匹配,用
s.str.findall(r"d{4}-d{2}-d{2}"),返回 list 类型的 Series - 注意
extract遇到不匹配会填NaN,而findall返回空 list,业务逻辑里要分别处理
清洗混合符号字符串:空格、不可见字符、HTML 实体怎么一并干掉
真实数据常混着 (不间断空格)、u200b(零宽空格)、& 这类东西,单靠 strip() 或 replace() 不够用。
- 先用
str.replace清 HTML 实体:s.str.replace(r"&", "&", regex=False).str.replace(r"<", " - 再用正则清不可见字符:
s.str.replace(r"[u200b-u200fu2028-u2029]+", " ", regex=True),把它们全换成普通空格 - 最后
str.strip().str.replace(r"s+", " ", regex=True)压缩多余空白 —— 注意这里s包含换行和制表符,比只清空格更彻底 - 别忘了
astype(str)预处理:如果列里有None或数字,直接调str.xxx会变成字符串"None"或科学计数法,得先s.fillna("").astype(str)
性能陷阱:为什么在大 DataFrame 上用 str.extract 很慢
str.extract 底层调用的是 Python 的 re 模块,逐行编译正则、逐行匹配,没有向量化加速。10 万行以上就明显卡顿。
立即学习“Python免费学习笔记(深入)”;
- 优先用
str.contains+ 布尔索引粗筛,再对子集做extract,减少调用次数 - 正则尽量写死边界:比如
r"order_id:(d{6,8})"比r"order_id:(d+)"快,避免回溯爆炸 - 如果只是简单分隔符提取(如冒号、竖线),用
str.split().str.get(1)或str.partition(),比正则快 3–5 倍 - 极端情况考虑
apply+ 编译好的re.compile对象,复用 pattern 实例,避免重复编译
正则清洗真正麻烦的不是语法,而是得时刻想着:这个 pattern 在 null 值上会不会炸?在超长文本里会不会回溯到天荒地老?还有那个永远躲在角落的 ,不显式处理,它就永远在空格位置等着你。










