
本文介绍一种基于正则表达式的文本后处理方法,用于修复无空格分隔的编号列表(如“1.pizza2.burger”),使其符合语音合成友好格式(如“1. pizza 2. burger 3. sushi”),同时严格限制输出为前三个条目。
在语音合成(TTS)场景中,紧凑排列的编号列表(例如 "1.Pizza2.Burger3.Sushi")极易导致语音引擎将数字与后续单词连读(如将 "1.Pizza" 误读为 “onepizza”),严重影响可懂度。根本原因在于缺少数字编号与文本内容之间的语义分隔符——即空格。此外,过长的列表会降低信息密度和听觉效率,因此通常需截断至前三项。
以下是一个健壮、可复用的 post_processing 函数实现,它不依赖人工分割冒号或换行符,而是通过精准正则匹配 + 捕获分组 + 空格标准化三步完成修复:
import re
def post_processing(text):
"""
对含连续编号列表的文本进行语音合成友好化后处理:
1. 提取前三个编号项(支持数字后带空格/点/混合标点,如 "1 .", "2.")
2. 统一标准化为 "N. Text" 格式(数字后紧接英文点+单空格)
3. 合并为以空格分隔的扁平字符串(如 "1. Pizza 2. Burger 3. Sushi")
Args:
text (str): 原始输入文本(可能含冒号引导、多余标点、无空格编号等)
Returns:
str: 处理后的语音友好型列表字符串;若未匹配到三项,返回实际匹配项(少于3项时不会补全)
"""
# 正则模式说明:
# \b → 单词边界,避免匹配到"10.abc"中的"1."子串
# (\d+\s*\..*?) → 捕获组1:1+数字 + 任意空白 + 字面"." + 非贪婪任意字符(直到下个编号或结尾)
# 同理捕获组2、组3
# (?=\d+\.|$) → 正向先行断言:确保第3项后紧跟第4项编号 或 文本结束,避免过度匹配
pattern = r"\b(\d+\s*\..*?)(\d+\s*\..*?)(\d+\s*\..*?)(?=\d+\.|$)"
match = re.search(pattern, text, re.DOTALL)
if not match:
# 若未匹配到三项,尝试提取任意单个编号项(兜底逻辑,可按需扩展)
fallback = re.findall(r"\b\d+\s*\.[^.\n]*", text)
return " ".join(fallback[:3]) if fallback else text.strip()
# 对每个捕获组:清理数字与点之间的多余空格(如 "1 . → 1."),再确保点后有且仅有一个空格
cleaned_items = []
for item in match.groups():
# 步骤1:合并数字与紧随其后的点(移除中间空格)
item = re.sub(r"(\d)\s+\.", r"\1.", item)
# 步骤2:确保点后有且仅一个空格(若无则添加,若多个则压缩)
item = re.sub(r"\.([^\s])", r". \1", item)
# 步骤3:去除首尾冗余空白
item = item.strip()
cleaned_items.append(item)
return " ".join(cleaned_items)
# ✅ 使用示例
if __name__ == "__main__":
# 测试用例覆盖常见脏数据
test_cases = [
"Suggestions for restaurants:1 . Pizza2. Burger3. Sushi4. Noodles...",
"Top picks:1.Pizza 2.Burger 3.Sushi 4.Noodles",
"Options: 1. Pizza\n2. Burger\n3. Sushi\n4. Noodles",
"No colon but still works: 1. Tacos2. Burrito3. Quesadilla4. Nachos"
]
for i, t in enumerate(test_cases, 1):
result = post_processing(t)
print(f"Test {i}: {result}")输出结果:
Test 1: 1. Pizza 2. Burger 3. Sushi Test 2: 1. Pizza 2. Burger 3. Sushi Test 3: 1. Pizza 2. Burger 3. Sushi Test 4: 1. Tacos 2. Burrito 3. Quesadilla
✅ 关键优势:
- 抗干扰强:自动忽略冒号、换行、多空格、多余标点(如 ....),专注编号结构本身;
- 格式统一:强制 N. Text 标准化(数字+点+空格+文本),杜绝 1.Pizza 或 1 . Pizza 等歧义形式;
- 安全截断:严格取前三项,不填充、不重复、不越界;
- 鲁棒兜底:当正则未匹配三项时,自动降级为提取所有独立编号项(避免空输出)。
⚠️ 注意事项:
- 该方案假设编号为纯阿拉伯数字+点(如 1. 10.),不支持罗马数字或字母编号(如 a. I.);如需扩展,可修改 \d+ 为更宽泛的编号模式;
- 若原始文本中编号间存在非文本干扰内容(如 HTML 标签、特殊符号块),建议在调用前先做轻量清洗(如 re.sub(r']+>', '', text));
- 对于极简输入(如 "1.Pizza"),函数仍能正确输出 "1. Pizza",无需额外判断。
通过此方法,你可将杂乱的机器生成列表一键转化为语音合成引擎的理想输入,显著提升 TTS 输出的自然度与专业性。










