如何用正则表达式精准分割含嵌套逗号的结构化产品数据

本文介绍如何使用 python 正则表达式,准确提取以“数字+冒号”开头、中间可含任意逗号(如产品名、规格)的独立产品记录,避免被内部逗号错误截断。

在处理数据库导出的非标准 CSV 数据时,常见一类“伪分隔”问题:字段本身含逗号(如 Radio - Antenna 2.4 GHz AB/C midi (10p)),而记录边界却依赖相同的逗号分隔——这导致 str.split(',') 或简单正则完全失效。核心挑战在于:识别真正的记录起始点(如 13351234:),并贪婪/非贪婪地捕获其后全部内容,直到下一个合法起始点或字符串结尾。

推荐使用 re.findall() + 前瞻断言(lookahead) 方案,语义清晰、鲁棒性强:

import re

text = "13371337:Bat,TH,Li-Met,Blub,9.5V,370mAHr,1/2_AA-Cell,50pcs,13351234:Radio - Antenna 2.4 GHz AB/C midi (10p),15642345:Board SMB - Some Magic Board,95653345:Board SMK 6 - Some Magic Knobs - Mod6,56735632:Control Unit Z65 - Mod9"

pattern = r"\b[0-9]{5,9}:.*?(?=,\b[0-9]{5,9}:|$)"
products = re.findall(pattern, text)
for p in products:
    print(repr(p))

关键解析:

  • \b[0-9]{5,9}: —— 精确匹配 5–9 位数字 + 冒号,\b 防止误匹配长数字中的子串(如 12345678 中的 23456);
  • .*? —— 非贪婪匹配任意字符(含逗号),确保尽可能少地消耗,为后续前瞻留出空间;
  • (?=,\b[0-9]{5,9}:|$) —— 正向先行

    断言
    :匹配位置必须满足“后面紧跟 ,数字: 或字符串结尾”,不消耗字符,从而精准界定每条记录终点。

⚠️ 注意事项:

  • 若原始数据首尾有空格或换行,建议预处理:text.strip();
  • 若产品编号可能含前导零(如 0012345),需将 [0-9]{5,9} 改为 \d{5,9} 并确认是否允许前导零;
  • 若必须用 re.split()(如需保留分隔符逻辑),可采用零宽断言:r"\b(?

该方案已通过多组边界测试(含末尾无逗号、单条记录、超长规格字段等),是处理此类半结构化文本的工业级实践。